Solomon Raja
Solomon Raja

Reputation: 1800

Merge multiple array of objects based on a key

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.

Upvotes: 0

Views: 693

Answers (2)

zb22
zb22

Reputation: 3231

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));

Upvotes: 1

PAG
PAG

Reputation: 26

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.

Upvotes: 1

Related Questions