Grouping elements in array by multiple properties是与我的问题最接近的匹配,因为它确实通过数组中的多个键对对象进行分组。问题是这个解决方案没有总结属性值然后删除重复项,而是将所有重复项嵌入到二维数组中。
预期行为
我有一组对象,必须按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}
];
只有当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);
但输出
[{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}]
如何让我的功能按形状和颜色正确分组对象?即总结他们的价值并删除重复项?
答案 0 :(得分:18)
将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);
如果您可以使用ES6,则使用Map收集值,然后通过spreading 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);
答案 1 :(得分:3)
您可以使用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)

答案 2 :(得分:3)
您可以使用哈希表和键来分组相同的组。
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);

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

答案 3 :(得分:3)
使用此方法来指定多个属性:
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];
})
}
像这样调用此方法
var result = Utils.groupBy(arr, function (item) {
return [item.shape, item.color];
});
答案 4 :(得分:2)
如果您需要基于color或shape属性的“二手”和“实例”数组;那么您可以使用此代码。
(PS:我知道这不是您想要的,但将来可能会帮助某人。为此,也正在重复使用Nenand's代码。如果该代码对您有用,请感谢他))>
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, YourArrayName : [] };
grouped.push(hash[key]);
}
['used'].forEach(function (k) { hash[key]['YourArrayName'].push({ used : o['used'], instances : o['instances'] }) });
});
console.log(grouped);
输出将像
答案 5 :(得分:1)
我有一个建议给你。 如果您想让它更容易,您可以尝试使用Underscore库:http://underscorejs.org/
我尽快使用它并得到了正确的结果:
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 byshape = _.groupBy(arr, 'shape');
var bycolor = _.map(byshape, function(array) {
return _.groupBy(array, 'color')
});
var output = [];
_.each(bycolor, function(arrayOfShape) {
_.each(arrayOfShape, function(arrayOfColor) {
var computedItem = {shape: "", color: "", used: 0, instances: 0};
_.each(arrayOfColor, function(item) {
computedItem.shape = item.shape;
computedItem.color = item.color;
computedItem.used += item.used;
computedItem.instances += item.instances;
});
output.push(computedItem);
});
});
console.log(output);
此解决方案将第一个数据分组,然后您可以执行您想要的操作,例如,计算数据为ypur wish。
也许您可以优化它,如果您需要更多帮助,请告诉我
答案 6 :(得分:0)
/**
* Groups an array of objects with multiple properties.
*
* @param {Array} array: the array of objects to group
* @param {Array} props: the properties to groupby
* @return {Array} an array of arrays with the grouped results
*/
const groupBy = ({ Group: array, By: props }) => {
getGroupedItems = (item) => {
returnArray = [];
let i;
for (i = 0; i < props.length; i++) {
returnArray.push(item[props[i]]);
}
return returnArray;
};
let groups = {};
let i;
for (i = 0; i < array.length; i++) {
const arrayRecord = array[i];
const group = JSON.stringify(getGroupedItems(arrayRecord));
groups[group] = groups[group] || [];
groups[group].push(arrayRecord);
}
return Object.keys(groups).map((group) => {
return groups[group];
});
};
示例:
假设我们有一个对象数组。每个对象都包含有关一个人和所拥有金钱的信息。我们要为所有具有相同国籍和性别的人总结金钱。
const data = [
{Name: 'George', Surname: 'Best', Country: 'Great Britain', Gender: 'Male', Money:8000},
{Name: 'Orion', Surname: 'Papathanasiou', Country: 'Greece', Gender: 'Male', Money: 2000},
{Name: 'Mairy', Surname: 'Wellbeck', Country: 'Great Britain', Gender: 'Female', Money:5000},
{Name: 'Thanasis', Surname: 'Papathanasiou', Country: 'Greece',Gender: 'Male', Money: 3200},
{Name: 'George', Surname: 'Washington', Country: 'Great Britain', Gender: 'Male',Money:4200},
{Name: 'Orfeas', Surname: 'Kalaitzis', Country: 'Greece', Gender: 'Male', Money: 7643},
{Name: 'Nick', Surname: 'Wellington', Country: 'USA', Gender: 'Male', Money:1000},
{Name: 'Kostas', Surname: 'Antoniou', Country: 'Greece', Gender: 'Male', Money: 8712},
{Name: 'John', Surname: 'Oneal', Country: 'USA', Gender: 'Male', Money:98234},
{Name: 'Paulos', Surname: 'Stamou', Country: 'Greece', Gender: 'Male', Money: 3422},
{Name: 'Soula', Surname: 'Spuropoulou', Country: 'Greece', Gender: 'Female', Money:400},
{Name: 'Paul', Surname: 'Pierce', Country: 'USA', Gender: 'Male',Money: 13000},
{Name: 'Helen', Surname: 'Smith', Country: 'Great Britain', Gender: 'Female', Money:1000},
{Name: 'Cathrine', Surname: 'Bryant', Country: 'Great Britain', Gender: 'Female', Money: 8712},
{Name: 'Jenny', Surname: 'Scalabrini', Country: 'USA', Gender: 'Female', Money:92214}];
const groupByProperties = ['Country', 'Gender'];
调用函数:
const groupResult = groupBy( {Group: data, By: groupByProperties} );
分组结果为:
(6) [Array(2), Array(5), Array(3), Array(3), Array(1), Array(1)]
0: Array(2)
0: {Name: "George", Surname: "Best", Country: "Great Britain", Gender: "Male", Money: 8000}
1: {Name: "George", Surname: "Washington", Country: "Great Britain", Gender: "Male", Money: 4200}
length: 2
__proto__: Array(0)
1: Array(5)
0: {Name: "Orion", Surname: "Papathanasiou", Country: "Greece", Gender: "Male", Money: 2000}
1: {Name: "Thanasis", Surname: "Papathanasiou", Country: "Greece", Gender: "Male", Money: 3200}
2: {Name: "Orfeas", Surname: "Kalaitzis", Country: "Greece", Gender: "Male", Money: 7643}
3: {Name: "Kostas", Surname: "Antoniou", Country: "Greece", Gender: "Male", Money: 8712}
4: {Name: "Paulos", Surname: "Stamou", Country: "Greece", Gender: "Male", Money: 3422}
length: 5
__proto__: Array(0)
2: Array(3)
0: {Name: "Mairy", Surname: "Wellbeck", Country: "Great Britain", Gender: "Female", Money: 5000}
1: {Name: "Helen", Surname: "Smith", Country: "Great Britain", Gender: "Female", Money: 1000}
2: {Name: "Cathrine", Surname: "Bryant", Country: "Great Britain", Gender: "Female", Money: 8712}
length: 3
__proto__: Array(0)
3: Array(3)
0: {Name: "Nick", Surname: "Wellington", Country: "USA", Gender: "Male", Money: 1000}
1: {Name: "John", Surname: "Oneal", Country: "USA", Gender: "Male", Money: 98234}
2: {Name: "Paul", Surname: "Pierce", Country: "USA", Gender: "Male", Money: 13000}
length: 3
__proto__: Array(0)
4: Array(1)
0: {Name: "Soula", Surname: "Spuropoulou", Country: "Greece", Gender: "Female", Money: 400}
length: 1
__proto__: Array(0)
5: Array(1)
0: {Name: "Jenny", Surname: "Scalabrini", Country: "USA", Gender: "Female", Money: 92214}
length: 1
__proto__: Array(0)
length: 6
__proto__: Array(0)
因此,我们得到了6个数组。每个数组都按Country
和Gender
遍历每个数组,我们可以总结一下钱!
const groupBy = ({ Group: array, By: props }) => {
getGroupedItems = (item) => {
returnArray = [];
let i;
for (i = 0; i < props.length; i++) {
returnArray.push(item[props[i]]);
}
return returnArray;
};
let groups = {};
let i;
for (i = 0; i < array.length; i++) {
const arrayRecord = array[i];
const group = JSON.stringify(getGroupedItems(arrayRecord));
groups[group] = groups[group] || [];
groups[group].push(arrayRecord);
}
return Object.keys(groups).map((group) => {
return groups[group];
});
};
const data = [
{Name: 'George', Surname: 'Best', Country: 'Great Britain', Gender: 'Male', Money:8000},
{Name: 'Orion', Surname: 'Papathanasiou', Country: 'Greece', Gender: 'Male', Money: 2000},
{Name: 'Mairy', Surname: 'Wellbeck', Country: 'Great Britain', Gender: 'Female', Money:5000},
{Name: 'Thanasis', Surname: 'Papathanasiou', Country: 'Greece',Gender: 'Male', Money: 3200},
{Name: 'George', Surname: 'Washington', Country: 'Great Britain', Gender: 'Male',Money:4200},
{Name: 'Orfeas', Surname: 'Kalaitzis', Country: 'Greece', Gender: 'Male', Money: 7643},
{Name: 'Nick', Surname: 'Wellington', Country: 'USA', Gender: 'Male', Money:1000},
{Name: 'Kostas', Surname: 'Antoniou', Country: 'Greece', Gender: 'Male', Money: 8712},
{Name: 'John', Surname: 'Oneal', Country: 'USA', Gender: 'Male', Money:98234},
{Name: 'Paulos', Surname: 'Stamou', Country: 'Greece', Gender: 'Male', Money: 3422},
{Name: 'Soula', Surname: 'Spuropoulou', Country: 'Greece', Gender: 'Female', Money:400},
{Name: 'Paul', Surname: 'Pierce', Country: 'USA', Gender: 'Male',Money: 13000},
{Name: 'Helen', Surname: 'Smith', Country: 'Great Britain', Gender: 'Female', Money:1000},
{Name: 'Cathrine', Surname: 'Bryant', Country: 'Great Britain', Gender: 'Female', Money: 8712},
{Name: 'Jenny', Surname: 'Scalabrini', Country: 'USA', Gender: 'Female', Money:92214}];
const groupByProperties = ['Country', 'Gender'];
const groupResult = groupBy( {Group: data, By: groupByProperties} );
console.log(groupResult);
答案 7 :(得分:0)
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}
];
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);
**Output:**
[
{
"color": "red",
"shape": "square",
"used": 11,
"instances": 9
},
{
"color": "blue",
"shape": "circle",
"used": 4,
"instances": 4
}
]
thats all perfetcly working.
Enjoy your coding....
答案 8 :(得分:0)
用户要求的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];
});
}
答案 9 :(得分:0)
如果您希望按条件字段使用groupBy键,则这里是@Abbes答案的修改:
@Embeddable
public class UserSettingId implements Serializable {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "setting")
private Setting setting;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user")
private User user;
public UserSettingId() {
}
public UserSettingId(Setting setting, User user) {
this.setting = setting;
this.user = user;
}
public Setting getSetting() {
return setting;
}
public void setSetting(Setting setting) {
this.setting = setting;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof UserSettingId)) return false;
UserSettingId that = (UserSettingId) o;
return setting.equals(that.setting) &&
user.equals(that.user);
}
@Override
public int hashCode() {
return Objects.hash(setting, user);
}
}
并像这样使用它:
function groupBy(array, f) {
let groups = {};
array.forEach((o) => {
var group = f(o).join('-');
groups[group] = groups[group] || [];
groups[group].push(o);
});
return groups;
}
答案 10 :(得分:0)
这是一个更通用的分组和求和功能,它接受对象数组,要进行分组的键数组和要求和的键数组。
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;
}, {})
);
}
演示:
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}
];
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;
}, {})
);
}
const res = groupAndSum(arr, ['shape', 'color'], ['used', 'instances']);
console.log(res);
答案 11 :(得分:0)
1.sumkeys 3.groupkeys
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}
];
function groupbykeys(arr, groupKeys, sumKeys){
var hash = Object.create(null),
grouped = [];
arr.forEach(function (o) {
var key = groupKeys.map(function (k) { return o[k]; }).join('|');
if (!hash[key]) {
hash[key] = Object.keys(o).reduce((result, key)=> {
result[key]=o[key];
if(sumKeys.includes(key))
result[key]=0;
return result;
}, { }); //map_(o) //{ shape: o.shape, color: o.color, used: 0, instances: 0 };
grouped.push(hash[key]);
}
sumKeys.forEach(function (k) { hash[key][k] += o[k]; });
});
return grouped;
}
var result=groupbykeys(arr,['shape','color'],['used','instances']);
console.log(result)