0

I need to merge a list of array of objects by a key. I tried to find materials online but ended up only on merging 2 array of objects.

But I have multiple array of objects in an array.

response = [
    [
        {
            "topic": "Topic 1",
            "avgwk38": 5
        },
        {
            "topic": "Topic 2",
            "avgwk38": 86
        },
        {
            "topic": "Topic 3",
            "avgwk38": 6
        }
    ],
    [
        {
            "topic": "Topic 1",
            "avgwk39": 25
        },
        {
            "topic": "Topic 2",
            "avgwk39": 32
        },
        {
            "topic": "Topic 3",
            "avgwk39": 4
        }
    ]
]

Here is my expected result.

[
    {
        "topic": "Topic 1",
        "avgwk38": 5,
        "avgwk39": 25
    },
    {
        "topic": "Topic 2",
        "avgwk38": 86,
        "avgwk39": 32
    },
    {
        "topic": "Topic 3",
        "avgwk38": 6,
        "avgwk39": 4
    }
]

Please help me out to resolve this.

Solomon Raja
  • 1,341
  • 1
  • 14
  • 23
  • Does this answer your question? [Javascript: Merge Two Arrays of Objects, Only If Not Duplicate (Based on Specified Object Key)](https://stackoverflow.com/questions/54134156/javascript-merge-two-arrays-of-objects-only-if-not-duplicate-based-on-specifi) – NullDev Oct 13 '20 at 10:16
  • You are going to merge objects based on same `topic` key value/ – Derek Wang Oct 13 '20 at 10:17
  • @NullDev I think the solution provided is limited to 2 arrays (old and new array) – Solomon Raja Oct 13 '20 at 10:30

2 Answers2

1

You could flatten your array and reduce values.

response.flat().reduce((acc, value) => {
  let existingValueIndex = acc.findIndex(obj => obj.topic === value.topic);
  if (existingValueIndex === -1) {
    acc.push({ ...value });
    return acc;
  }

  acc[existingValueIndex] = {
    ...acc[existingValueIndex],
    ...value,
  };
  return acc;
}, []);

It's not really efficient if you have big arrays. You can also use a Set to keep track on Topic names and prevent searching in the array for each iteration.

PAG
  • 26
  • 4
  • Thank you @PAG this is working like a charm. I have only small arrays, as this is a monthly view with each week's average value. – Solomon Raja Oct 13 '20 at 10:35
1

Here is another way of solving this,
Making an object of topics with a unique topic, which contains the properties of each topic item.

Finally using Object.values() to make this an array.

const response = [
    [
        {
            "topic": "Topic 1",
            "avgwk38": 5
        },
        {
            "topic": "Topic 2",
            "avgwk38": 86
        },
        {
            "topic": "Topic 3",
            "avgwk38": 6
        }
    ],
    [
        {
            "topic": "Topic 1",
            "avgwk39": 25
        },
        {
            "topic": "Topic 2",
            "avgwk39": 32
        },
        {
            "topic": "Topic 3",
            "avgwk39": 4
        }
    ]
]

const obj = response.flat().reduce((acc, curr) => {
  if(!acc[curr.topic]) {
    acc[curr.topic] = {
      ...curr
    }
  } else {
    acc[curr.topic] = {
      ...acc[curr.topic],
      ...curr
    }
  }

  return acc;
}, {});

console.log(Object.values(obj));
zb22
  • 3,126
  • 3
  • 19
  • 34