Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
263 views
in Technique[技术] by (71.8m points)

javascript - Group objects by multiple properties in array then sum up their values

Grouping elements in array by multiple properties is the closest match to my question as it indeed groups objects by multiple keys in an array. Problem is this solution doesn't sum up the properties value then remove the duplicates, it instead nests all the duplicates in a two-dimensional arrays.

Expected behavior

I have an array of objects which must be grouped by shape and color.

var arr = [
    {shape: 'square', color: 'red', used: 1, instances: 1},
    {shape: 'square', color: 'red', used: 2, instances: 1},
    {shape: 'circle', color: 'blue', used: 0, instances: 0},
    {shape: 'square', color: 'blue', used: 4, instances: 4},
    {shape: 'circle', color: 'red', used: 1, instances: 1},
    {shape: 'circle', color: 'red', used: 1, instances: 0},
    {shape: 'square', color: 'blue', used: 4, instances: 5},
    {shape: 'square', color: 'red', used: 2, instances: 1}
];

Objects in this array are considered duplicates only if both their shape and color are the same. If they are, I want to respectively sum up their used and instances values then delete the duplicates.

So in this example result array may only contain four combinations : square red, square blue, circle red, circle blue

Problem

I tried a simpler approach here:

var arr = [
    {shape: 'square', color: 'red', used: 1, instances: 1},
    {shape: 'square', color: 'red', used: 2, instances: 1},
    {shape: 'circle', color: 'blue', used: 0, instances: 0},
    {shape: 'square', color: 'blue', used: 4, instances: 4},
    {shape: 'circle', color: 'red', used: 1, instances: 1},
    {shape: 'circle', color: 'red', used: 1, instances: 0},
    {shape: 'square', color: 'red', used: 4, instances: 4},
    {shape: 'square', color: 'red', used: 2, instances: 2}
];

result = [];

arr.forEach(function (a) {
    if ( !this[a.color] && !this[a.shape] ) {
        this[a.color] = { color: a.color, shape: a.shape, used: 0, instances: 0 };
        result.push(this[a.color]);
    } 
    this[a.color].used += a.used;
    this[a.color].instances += a.instances;
}, Object.create(null));

console.log(result);
question from:https://stackoverflow.com/questions/46794232/group-objects-by-multiple-properties-in-array-then-sum-up-their-values

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Use Array#reduce with a helper object to group similar objects. For each object, check if the combined shape and color exists in the helper. If it doesn't, add to the helper using Object#assign to create a copy of the object, and push to the array. If it does, add it's values to used and instances.

var arr = [{"shape":"square","color":"red","used":1,"instances":1},{"shape":"square","color":"red","used":2,"instances":1},{"shape":"circle","color":"blue","used":0,"instances":0},{"shape":"square","color":"blue","used":4,"instances":4},{"shape":"circle","color":"red","used":1,"instances":1},{"shape":"circle","color":"red","used":1,"instances":0},{"shape":"square","color":"blue","used":4,"instances":5},{"shape":"square","color":"red","used":2,"instances":1}];

var helper = {};
var result = arr.reduce(function(r, o) {
  var key = o.shape + '-' + o.color;
  
  if(!helper[key]) {
    helper[key] = Object.assign({}, o); // create a copy of o
    r.push(helper[key]);
  } else {
    helper[key].used += o.used;
    helper[key].instances += o.instances;
  }

  return r;
}, []);

console.log(result);

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...