-1

I have array of objects:

[{sku: "BS-WHITE-1", GB: 15, total: 0, inbound: 0, available: 0, …},
{sku: "BS-WHITE-1", DE: 4},
{sku: "BS-WHITE-1", ES: 0},
{sku: "BS-WHITE-1", IT: 3},
{sku: "BS-WHITE-1", FR: 0},
{sku: "BS-WHITE-2", GB: 19, total: 40, inbound: 0, available: 40, …}
{sku: "BS-WHITE-2", DE: 2},
{sku: "BS-WHITE-2", FR: 5},
{sku: "BS-WHITE-2", ES: 3},
{sku: "BS-WHITE-2", IT: 6},
{sku: "BS-WHITE-3", GB: 21, total: 51, inbound: 1, available: 50, …}
{sku: "BS-WHITE-3", DE: 1},
{sku: "BS-WHITE-3", ES: 1},
{sku: "BS-WHITE-3", IT: 2},
{sku: "BS-WHITE-3", FR: 2},
{sku: "BS-WHITE-4", GB: 43, total: 42, inbound: 8, available: 31, …},
{sku: "BS-WHITE-4", DE: 8},
{sku: "BS-WHITE-4", FR: 7},
{sku: "BS-WHITE-4", ES: 3},
{sku: "BS-WHITE-4", IT: 17}]

And I want to merge objects based on key "sku" to get

[{sku: "BS-WHITE-1", GB: 15, DE: 4,ES: 0,IT: 3, FR: 0, total: 0, …},
{sku: "BS-WHITE-2", GB: 19, DE: 2,ES: 3,IT:6, FR: 5, total: 0, …},
{sku: "BS-WHITE-3", GB: 21, DE: 1,ES: 1,IT:2, FR: 2, total: 0, …},
{sku: "BS-WHITE-4", GB: 43, DE: 8,ES: 3,IT:17, FR: 7, total: 0, …}]

to do it I use reduce

const out = map.reduce((a, v) => {
  if (a[v.sku]) {
    a[v.sku].GB = a[v.sku].GB; //ok
    a[v.sku].DE = (v.DE) ? v.DE : 222; //?
    a[v.sku].FR = a[v.sku].FR ? a[v.sku].FR : 555; //?
    a[v.sku].IT = 2; //
    a[v.sku].ES = a[v.sku].ES; //?
  } else {
    a[v.sku] = v;
  }
  return a;
}, {});
console.log(Object.values(out));
<script>
const map = [{sku: "BS-WHITE-1", GB: 15, total: 0, inbound: 0, available: 0 },
    {sku: "BS-WHITE-1", DE: 4},
    {sku: "BS-WHITE-1", ES: 0},
    {sku: "BS-WHITE-1", IT: 3},
    {sku: "BS-WHITE-1", FR: 0},
    {sku: "BS-WHITE-2", GB: 19, total: 40, inbound: 0, available: 40},
    {sku: "BS-WHITE-2", DE: 2},
    {sku: "BS-WHITE-2", FR: 5},
    {sku: "BS-WHITE-2", ES: 3},
    {sku: "BS-WHITE-2", IT: 6},
    {sku: "BS-WHITE-3", GB: 21, total: 51, inbound: 1, available: 50},
    {sku: "BS-WHITE-3", DE: 1},
    {sku: "BS-WHITE-3", ES: 1},
    {sku: "BS-WHITE-3", IT: 2},
    {sku: "BS-WHITE-3", FR: 2},
    {sku: "BS-WHITE-4", GB: 43, total: 42, inbound: 8, available: 31},
    {sku: "BS-WHITE-4", DE: 8},
    {sku: "BS-WHITE-4", FR: 7},
    {sku: "BS-WHITE-4", ES: 3},
    {sku: "BS-WHITE-4", IT: 17}]
</script>    

Unfortunately, I can't find values of keys DE, FR, IT, ES which are in other objects. Only the first GB is OK. Any help?

mplungjan
  • 169,008
  • 28
  • 173
  • 236
awariat
  • 331
  • 1
  • 5
  • 22

2 Answers2

2

Here is a use Array.prototype.reduce to alter the shape of array

let data = [
    {sku: "BS-WHITE-1", GB: 15, total: 0, inbound: 0, available: 0},
    {sku: "BS-WHITE-1", DE: 4},
    {sku: "BS-WHITE-1", ES: 0},
    {sku: "BS-WHITE-1", IT: 3},
    {sku: "BS-WHITE-1", FR: 0},
    {sku: "BS-WHITE-2", GB: 19, total: 40, inbound: 0, available: 40},
    {sku: "BS-WHITE-2", DE: 2},
    {sku: "BS-WHITE-2", FR: 5},
    {sku: "BS-WHITE-2", ES: 3},
    {sku: "BS-WHITE-2", IT: 6},
    {sku: "BS-WHITE-3", GB: 21, total: 51, inbound: 1, available: 50},
    {sku: "BS-WHITE-3", DE: 1},
    {sku: "BS-WHITE-3", ES: 1},
    {sku: "BS-WHITE-3", IT: 2},
    {sku: "BS-WHITE-3", FR: 2},
    {sku: "BS-WHITE-4", GB: 43, total: 42, inbound: 8, available: 31},
    {sku: "BS-WHITE-4", DE: 8},
    {sku: "BS-WHITE-4", FR: 7},
    {sku: "BS-WHITE-4", ES: 3},
    {sku: "BS-WHITE-4", IT: 17}
];

const result = data.reduce((accumulator, current) => {
    let itemIndex = accumulator.findIndex(item => item.sku === current.sku);
    if(itemIndex != -1) {
        accumulator[itemIndex] = {...accumulator[itemIndex], ...current};
    } else {
        accumulator = accumulator.concat(current);
    }
    return accumulator;
}, []);

console.log(result);
Yves Kipondo
  • 5,289
  • 1
  • 18
  • 31
1

You could assign the objects to the group or generate a new object for this group.

const
    data = [{ sku: "BS-WHITE-1", GB: 15, total: 0, inbound: 0, available: 0 }, { sku: "BS-WHITE-1", DE: 4 }, { sku: "BS-WHITE-1", ES: 0 }, { sku: "BS-WHITE-1", IT: 3 }, { sku: "BS-WHITE-1", FR: 0 }, { sku: "BS-WHITE-2", GB: 19, total: 40, inbound: 0, available: 40 }, { sku: "BS-WHITE-2", DE: 2 }, { sku: "BS-WHITE-2", FR: 5 }, { sku: "BS-WHITE-2", ES: 3 }, { sku: "BS-WHITE-2", IT: 6 }, { sku: "BS-WHITE-3", GB: 21, total: 51, inbound: 1, available: 50 }, { sku: "BS-WHITE-3", DE: 1 }, { sku: "BS-WHITE-3", ES: 1 }, { sku: "BS-WHITE-3", IT: 2 }, { sku: "BS-WHITE-3", FR: 2 }, { sku: "BS-WHITE-4", GB: 43, total: 42, inbound: 8, available: 31 }, { sku: "BS-WHITE-4", DE: 8 }, { sku: "BS-WHITE-4", FR: 7 }, { sku: "BS-WHITE-4", ES: 3 }, { sku: "BS-WHITE-4", IT: 17 }],
    result = Object.values(data.reduce((r, o) => {
        Object.assign(r[o.sku] ??= {}, o);
        return r;
    }, {}));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Hi Nina. I like this answer but jshint shows errors (the code works itself in Visual studio code). – awariat Mar 08 '22 at 13:11
  • maybe because of [logical nullish assignment `??=`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_nullish_assignment): `r[o.sku] ??= {}` you could replace without, like `r[o.sku] = r[o.sku] || {}`. – Nina Scholz Mar 08 '22 at 13:12
  • Yes, you're right, Now is OK. – awariat Mar 08 '22 at 13:17