Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript - Reduce Array of Objects by Key [duplicate]

Working with an array of objects like:

const arr = [
  {name: "qewregf dqewafs", value: "qewregf dqewafs answer", count: 2},
  {name: "survey with select", value: "survey with select answer", count: 2},
  {name: "werasd", value: "Donald", count: 1},
  {name: "werasd", value: "Jim", count: 1}
];

I am trying to reduce the array on matching values for the name key and achieve an desired output like:

desiredOutput = [
  {name: "qewregf dqewafs", data: [{value: "qewregf dqewafs answer", count: 2}]},
  {name: "survey with select", data: [{value: "survey with select answer", count: 2}]},
  {name: "werasd", data: [{value: "Donald", count: 1}, {value: "Jim", count: 1}]}
]

This attempt reduces the array, but I am missing how to merge the nested values without overwriting.

const arr = [{"name":"qewregf dqewafs","value":"qewregf dqewafs answer","count":2},{"name":"survey with select","value":"survey with select answer","count":2},{"name":"werasd","value":"Donald","count":1},{"name":"werasd","value":"Jim","count":1}];

const result = arr.reduce((acc, d) => {
  const found = acc.find(a => a.name === d.name);
  const value = { name: d.name, val: d.value };
  if (found) {
    acc.push(...value);
  }
  else {
    acc.push({ name: d.name, data: [{ value: d.value }, { count: d.count }] });
  }
  return acc;
}, []);

console.log(result);

What am I missing?

like image 743
proph3t Avatar asked Aug 20 '18 17:08

proph3t


People also ask

How do you remove duplicates in array of objects in JS?

Array. filter() removes all duplicate objects by checking if the previously mapped id-array includes the current id ( {id} destructs the object into only its id).

How can I remove the duplicate items in an array?

We can remove duplicate element in an array by 2 ways: using temporary array or using separate index. To remove the duplicate element from array, the array must be in sorted order. If array is not sorted, you can sort it by calling Arrays. sort(arr) method.

How do you merge two arrays of objects in JavaScript and de duplicate items?

Answer: Use the indexOf() Method You can use the indexOf() method in conjugation with the push() remove the duplicate values from an array or get all unique values from an array in JavaScript.

Can objects have duplicate keys JavaScript?

No, JavaScript objects cannot have duplicate keys. The keys must all be unique.


2 Answers

You codes are a little close to the goal, just need to adjust something.

Please see the comment in below demo:

  1. When acc.find doesn't find anything, then push one element {name:d.name, data: [value]}

  2. if found, then push one {value: ...} into data property.

const arr = [
  {name: "qewregf dqewafs", value: "qewregf dqewafs answer", count: 2},
  {name: "survey with select", value: "survey with select answer", count: 2},
  {name: "werasd", value: "Donald", count: 1},
  {name: "werasd", value: "Jim", count: 1}
];

const result = arr.reduce((acc, d) => {
  const found = acc.find(a => a.name === d.name);
  //const value = { name: d.name, val: d.value };
  const value = { value: d.value, count: d.count }; // the element in data property
  if (!found) {
    //acc.push(...value);
    acc.push({name:d.name, data: [value]}) // not found, so need to add data property
  }
  else {
    //acc.push({ name: d.name, data: [{ value: d.value }, { count: d.count }] });
    found.data.push(value) // if found, that means data property exists, so just push new element to found.data.
  }
  return acc;
}, []);

console.log(result)
like image 61
Sphinx Avatar answered Sep 21 '22 09:09

Sphinx


You're not far off. This would be a simple change to two lines of your code to achieve it:

const arr = [
  {name: "qewregf dqewafs", value: "qewregf dqewafs answer", count: 2},
  {name: "survey with select", value: "survey with select answer", count: 2},
  {name: "werasd", value: "Donald", count: 1},
  {name: "werasd", value: "Jim", count: 1}
];

const result = arr.reduce((acc, d) => {
  const found = acc.find(a => a.name === d.name);
  const value = { name: d.name, val: d.value };
  if (found) {
    found.data.push(value);
  }
  else {
    acc.push({ name: d.name, data: [{ value: d.value, count: d.count }] });
  }
  return acc;
}, []);

console.log(result)

Here are the differences:

-     acc.push(...value);
+     found.data.push(value);


-    acc.push({ name: d.name, data: [{ value: d.value }, { count: d.count }] });
+    acc.push({ name: d.name, data: [{ value: d.value, count: d.count }] });
like image 39
Scott Sauyet Avatar answered Sep 23 '22 09:09

Scott Sauyet