問題描述
按多個屬性對數組中的元素進行分組是與我的問題最匹配,因為它確實通過數組中的多個鍵對對象進行分組.問題是這個解決方案沒有總結屬性值然后刪除重復項,而是將所有重復項嵌套在一個二維數組中.
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.
預期行為
我有一組對象,必須按 shape
和 color
分組.
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}
];
只有當 shape
和 color
相同時,此數組中的對象才被視為重復對象.如果是,我想分別總結它們的 used
和 instances
值,然后刪除重復項.
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.
所以在這個例子中,結果數組可能只包含四種組合:square red
、square blue
、circle red
、circle blue
So in this example result array may only contain four combinations : square red
, square blue
, circle red
, circle blue
問題
我在這里嘗試了一種更簡單的方法:
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);
但它輸出
[{shape: "square", color: "red", used: 11, instances: 9},
{shape: "circle", color: "blue", used: 4, instances: 4}]
而不是預期的結果:
[{shape: "square", color: "red", used: 5, instances: 3},
{shape: "circle", color: "red", used: 2, instances: 1},
{shape: "square", color: "blue", used: 11, instances: 9},
{shape: "circle", color: "blue", used: 0, instances: 0}]
如何讓我的函數按形狀和顏色正確分組對象?即總結它們的值并刪除重復項?
How can I get my function to properly group the objects by shape and color ? i.e. sum up their values and remove the duplicates ?
推薦答案
使用 Array#reduce 帶有一個輔助對象來對相似的對象進行分組.對于每個對象,檢查組合的 shape
和 color
是否存在于幫助程序中.如果沒有,請使用 添加到幫助程序Object#assign 創建對象的副本,并推送到數組.如果是,請將其值添加到 used
和 instances
.
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);
如果您可以使用 ES6,則使用 Map 收集值,然后通過 傳播 地圖#values:
If you can use ES6, you use a Map to collect the values, and then convert it back to an array by spreading the Map#values:
const 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}];
const result = [...arr.reduce((r, o) => {
const key = o.shape + '-' + o.color;
const item = r.get(key) || Object.assign({}, o, {
used: 0,
instances: 0
});
item.used += o.used;
item.instances += o.instances;
return r.set(key, item);
}, new Map).values()];
console.log(result);
這篇關于按數組中的多個屬性對對象進行分組,然后將它們的值相加的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!