Hal*_*100 16 javascript arrays duplicates
通过多个属性对数组中的元素进行分组是与我的问题最接近的匹配,因为它确实通过数组中的多个键对对象进行分组.问题是这个解决方案没有总结属性值然后删除重复项,而是将所有重复项嵌入二维数组中.
预期的行为
我有一个对象数组,必须按shape
和分组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}
];
Run Code Online (Sandbox Code Playgroud)
此数组中的对象仅在它们shape
和color
它们相同时才被视为重复.如果是,我想分别总结他们的used
和instances
值,然后删除重复项.
因此,在这个例子的结果阵列可以仅含有四种组合:square red
,square blue
,circle red
,circle blue
问题
我在这里尝试了一种更简单的方法:
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);
Run Code Online (Sandbox Code Playgroud)
但它输出
[{shape: "square", color: "red", used: 11, instances: 9},
{shape: "circle", color: "blue", used: 4, instances: 4}]
Run Code Online (Sandbox Code Playgroud)
而不是预期的结果:
[{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}]
Run Code Online (Sandbox Code Playgroud)
如何使我的功能按形状和颜色正确分组对象?即总结他们的价值并删除重复?
Ori*_*ori 29
将Array#reduce与辅助对象一起使用以对类似对象进行分组.对于每个对象,检查组合shape
并是否color
存在于帮助程序中.如果没有,请使用Object#assign添加到帮助程序以创建对象的副本,然后推送到该数组.如果是,请将其值添加到used
和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);
Run Code Online (Sandbox Code Playgroud)
如果你可以使用ES6,您可以使用地图收集的值,然后将其转换回一个数组蔓延的地图#值:
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);
Run Code Online (Sandbox Code Playgroud)
Abb*_*ine 10
使用此方法指定多个属性:
public static groupBy(array, f) {
let groups = {};
array.forEach(function (o) {
var group = JSON.stringify(f(o));
groups[group] = groups[group] || [];
groups[group].push(o);
});
return Object.keys(groups).map(function (group) {
return groups[group];
})
}
Run Code Online (Sandbox Code Playgroud)
像这样调用这个方法:
var result = Utils.groupBy(arr, function (item) {
return [item.shape, item.color];
});
Run Code Online (Sandbox Code Playgroud)
您可以使用哈希表和键对相同的组进行分组。
var array = [{ 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 }],
hash = Object.create(null),
grouped = [];
array.forEach(function (o) {
var key = ['shape', 'color'].map(function (k) { return o[k]; }).join('|');
if (!hash[key]) {
hash[key] = { shape: o.shape, color: o.color, used: 0, instances: 0 };
grouped.push(hash[key]);
}
['used', 'instances'].forEach(function (k) { hash[key][k] += o[k]; });
});
console.log(grouped);
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper { max-height: 100% !important; top: 0; }
Run Code Online (Sandbox Code Playgroud)
这是一个更通用的分组和求和函数,它接受一个对象数组、一个用于分组的键数组以及一个用于求和的键数组。
function groupAndSum(arr, groupKeys, sumKeys){
return Object.values(
arr.reduce((acc,curr)=>{
const group = groupKeys.map(k => curr[k]).join('-');
acc[group] = acc[group] || Object.fromEntries(
groupKeys.map(k => [k, curr[k]]).concat(sumKeys.map(k => [k, 0])));
sumKeys.forEach(k => acc[group][k] += curr[k]);
return acc;
}, {})
);
}
Run Code Online (Sandbox Code Playgroud)
演示:
function groupAndSum(arr, groupKeys, sumKeys){
return Object.values(
arr.reduce((acc,curr)=>{
const group = groupKeys.map(k => curr[k]).join('-');
acc[group] = acc[group] || Object.fromEntries(
groupKeys.map(k => [k, curr[k]]).concat(sumKeys.map(k => [k, 0])));
sumKeys.forEach(k => acc[group][k] += curr[k]);
return acc;
}, {})
);
}
Run Code Online (Sandbox Code Playgroud)
您可以使用reduce()
创建一个具有唯一shape|color
属性的对象并 Object.values()
返回这些值的数组。
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 result = Object.values(arr.reduce(function(r, e) {
var key = e.shape + '|' + e.color;
if (!r[key]) r[key] = e;
else {
r[key].used += e.used;
r[key].instances += e.instances
}
return r;
}, {}))
console.log(result)
Run Code Online (Sandbox Code Playgroud)
ES6按照用户要求回答:
// To call this function:
// const result = this.toolBox.multipleGroupByArray(
// dataArray, (property: IProperty) => [property.prop1, property.prop2, property.prop3]);
multipleGroupByArray(dataArray, groupPropertyArray) {
const groups = {};
dataArray.forEach(item => {
const group = JSON.stringify(groupPropertyArray(item));
groups[group] = groups[group] || [];
groups[group].push(item);
});
return Object.keys(groups).map(function(group) {
return groups[group];
});
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
16408 次 |
最近记录: |