0

I have been toying with the best way to go about doing this and have found some options but not one that preserves the format I am trying to keep for the array/object.

The overview is I have an array that gets random objects pushed into it and there can be duplicates of the same object, but I want to change it so there is only 1 of each object and instead, having a count property for each object.

An example of what I am working with and what I am aiming to have.

arr = [
  { Name: Item1, Value: 20 },
  { Name: Item2, Value: 20 },
  { Name: Item1, Value: 20 }
];

result = [
  { Name: Item1, Value: 20, Count: 2 },
  { Name: Item2, Value: 20, Count: 1 }
];

As a side note, I am wondering if it better to do this after the array is filled or if it is better to do this while pushing the objects into the array?

2
  • 2
    do you want to group by Name and Value, or only by Name? Commented Nov 14, 2018 at 21:07
  • Only by name, the values for each of the objects in the array will all be the same anyway. Commented Nov 14, 2018 at 21:18

4 Answers 4

2

Assuming the value of each item is the same, you can do a simple forEach loop. For each element, check to see if the object exists in 'result'. If so, increment the count, otherwise add it to the result array.

let result = [];

arr.forEach(item => {
  let resObj = result.find(resObj => resObj.Name === item.Name);
  resObj ? resObj.Count++ : result.push({'Name':item.Name, 'Value': item.Value, 'Count': 1});
});

console.log(result);

In this case, you don't want to use arr.map, since we're not updating the original array.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, this is just what I was thinking for how to do it, trying to get a good grasp on manipulating an array of objects.
1

If items are continuously being added, you can maintain an "index" (by Name) of objects you've already added to the array so that whenever a new object is added, you can update the count if it's already present or push it to the array if it's not:

var arr = [];
var index = {};

function addItem(o) {
  if (o.Name in index) {
    index[o.Name].Count += 1;
  } else {
    index[o.Name] = o;
    o.Count = 1;
    arr.push(o);
  }
}

addItem({
  Name: 'Item1',
  Value: 20
});
addItem({
  Name: 'Item2',
  Value: 20
});
addItem({
  Name: 'Item1',
  Value: 20
});

console.log(arr);

The benefit of this approach is that you don't have to recompute counts from scratch (which is an O(n) operation) every time you want to get the result array.

2 Comments

This doesn't match OPs expected output - he's adding a Count property, not incrementing Value
Thanks for posting this, I was thinking of how to do this beforehand, and have the Count already apart of the object. I never used an index before and had forgotten about it.
1

You can loop through the array and maintain 1 temporary object with "Name" as a key, If same name is found increment "count" by 1

let array = [{ Name: 'Item1', Value: 20 }, { Name: 'Item2', Value: 20 }, { Name: 'Item1', Value: 20 }]
    
let tempResult = {}
for (let d of array) {
  tempResult[d.Name] = { 
     count: 1, 
     ...d, 
     ...(tempResult[d.Name] &&  { count: tempResult[d.Name].count + 1 }) 
  }
}

let result = Object.values(tempResult)
console.log(result);

Comments

0

You could take a hash table and count same items.

var array = [{ Name: 'Item1', Value: 20 }, { Name: 'Item2', Value: 20 }, { Name: 'Item1', Value: 20 }],
    result = Object.values(array.reduce((r, { Name, Value }) => {
        r[Name] = r[Name] || { Name, Value, Count: 0 };
        r[Name].Count++;
        return r;
    }, {}));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.