繁体   English   中英

按数组中的多个属性对对象进行分组,然后求和它们的值

[英]Group objects by multiple properties in array then sum up their values

按多个属性对数组中的元素进行分组是最接近我的问题的匹配项,因为它确实按数组中的多个键对对象进行分组。 问题是这个解决方案没有总结属性值然后删除重复项,而是将所有重复项嵌套在二维 arrays 中。

预期行为

我有一组必须按shapecolor分组的对象。

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}
];

只有当它们的shapecolor都相同时,此数组中的对象才被认为是重复的。 如果是,我想分别总结它们的used值和instances值,然后删除重复项。

所以在这个例子中,结果数组可能只包含四种组合: square redsquare bluecircle redcircle 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}]

如何让我的 function 按形状和颜色对对象进行正确分组? 即总结他们的价值并删除重复项?

Array#reduce与辅助对象一起使用来对相似的对象进行分组。 对于每个对象,检查助手中是否存在组合的shapecolor 如果没有,请使用Object#assign添加到助手以创建对象的副本,然后推送到数组。 如果是,将它的值添加到usedinstances

 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来收集值,然后通过传播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);

使用此方法指定多个属性:

 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];
          });

您可以使用哈希表和键对相同的组进行分组。

 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; }

您可以使用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)

用户要求的 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];
    });
}

这是一个更通用的分组和求和函数,它接受一个对象数组、一个要分组的键数组和一个要求和的键数组。

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);

如果您想要 groupBy 键作为条件字段,那么这里是@Abbes 答案的修改:

function groupBy(array, f) {
    let groups = {};
    array.forEach((o) => {
        var group = f(o).join('-');
        groups[group] = groups[group] || [];
        groups[group].push(o);
    });
    return groups;
}

并像这样使用它:

groupBy(connectedServers, (item) => {
            return [item.key1, item.key2];
});

如果您需要基于颜色或形状属性的“已使用”和“实例”数组; 那么你可以使用这个代码。

(PS:我知道这不是你要找的,但将来它可能会帮助某人。我也为此重用了Nenand 的代码。如果代码对你有用,谢谢他)

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);

输出将类似于

控制台的结果

我有一个建议给你。 如果你想让它更容易做,你可以试试 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);

http://jsfiddle.net/oLyzdoo7/

该解决方案首先对数据进行分组,然后您可以执行您想要的操作,例如,按照您的意愿计算数据。

也许您可以优化它,如果您需要更多帮助,请告诉我

/**
  * 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 个数组。 每个数组按CountryGender分组

遍历每个数组,我们可以总结出钱!

 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);

    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....

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)

聚合到一个 object 中,以具有减少的形状和颜色的独特组合为键,然后从中取出值:

 const aggregate = xs => Object.values( xs.reduce((acc, {shape, color, used, instances}) => { const key = shape + color; acc[key]??= {shape, color, used: 0, instances: 0}; acc[key].used += used; acc[key].instances += instances; return acc; }, {}) ); console.log(aggregate(arr));
 <script> 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}]; </script>

我发现其中一些答案有点难以重用,所以这里有一个可重用的 function ,您可以传递您希望分组使用的键。

 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} ]; const groupByMultipleKeys = (items, keys) => items.reduce((acc, item) => { const isExistingItem = acc.flatMap(accItem => accItem).find(accItem => keys.every(key => accItem[key] === item[key]) ) if (isExistingItem) { return acc; } const allRelatedItems = items.filter(ungroupedItem => keys.every(key => ungroupedItem[key] === item[key]) ) acc.push(allRelatedItems) return acc }, []) const groupedItem = groupByMultipleKeys(arr, ['shape', 'color']) console.log('groupedItem', groupedItem)

  • 项目清单

更紧凑的 ES6 版本,它使用 JSON.stringify 来确保分组属性之间的正确分隔。

 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}]; let grouped = Object.values(arr.reduce((a,c)=> { let i = a[JSON.stringify([c.shape, c.color])]??= {...c, used: 0, instances: 0}; i.used += c.used; i.instances += c.instances; return a; }, {})); console.log(grouped);

或者,为了更容易指定任意分组属性和求和属性:

 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}]; function groupAndSum(arr, groupProps, sumProps) { return Object.values(arr.reduce((a,c)=> { let i = a[JSON.stringify(groupProps.map(p=>[p,c[p]]))]??= {...c, ...Object.fromEntries(sumProps.map(p=>[p, 0]))}; sumProps.forEach(p=>i[p]+=c[p]); return a; }, {})); } console.log(groupAndSum(arr, ['shape', 'color'], ['used', 'instances']));

const v = [{"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 groupBy<T>(
  arr: T[],
  vInitial: Partial<T>,
  fn: (curr: T, acc: T) => void,
  ...args: Array<keyof T>
) {
  return Array.from(
    arr
      .reduce((r, o) => {
        const key = args.map((k) => o[k]).join("|");

        const ob = Object.assign({}, o);

        const obj = {};

        for (const key of Object.keys(ob)) {
          if (
            vInitial != null &&
            vInitial.hasOwnProperty(key) &&
            vInitial[key] != null
          ) {
            obj[key] = vInitial[key];
          }
        }

        const item = r.get(key) ?? Object.assign({}, o, obj);

        fn(item, o);

        return r.set(key, item);
      }, new Map<string, T>())
      .values(),
  );
}

console.log(groupBy(
  v,
  {},
  (item, o) => {
    item.used += o.used;
    item.instances += o.instances;
  },
  'shape', 'color'));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM