按javascript中的属性对对象进行分组

时间:2013-04-08 20:03:07

标签: javascript underscore.js

如何转换:

[
    {food: 'apple', type: 'fruit'},
    {food: 'potato', type: 'vegetable'},
    {food: 'banana', type: 'fruit'},
]

进入这个:

[
    {type: 'fruit', foods: ['apple', 'banana']},
    {type: 'vegetable', foods: ['potato']}
]

使用javascript或下划线

6 个答案:

答案 0 :(得分:87)

假设原始列表包含在名为list的变量中:

_
.chain(list)
.groupBy('type')
.map(function(value, key) {
    return {
        type: key,
        foods: _.pluck(value, 'food')
    }
})
.value();

答案 1 :(得分:17)

不使用下划线:

var origArr = [
    {food: 'apple', type: 'fruit'},
    {food: 'potato', type: 'vegetable'},
    {food: 'banana', type: 'fruit'}
];

/*[
    {type: 'fruit', foods: ['apple', 'banana']},
    {type: 'vegetable', foods: ['potato']}
]*/

function transformArr(orig) {
    var newArr = [],
        types = {},
        i, j, cur;
    for (i = 0, j = orig.length; i < j; i++) {
        cur = orig[i];
        if (!(cur.type in types)) {
            types[cur.type] = {type: cur.type, foods: []};
            newArr.push(types[cur.type]);
        }
        types[cur.type].foods.push(cur.food);
    }
    return newArr;
}

console.log(transformArr(origArr));

DEMO: http://jsfiddle.net/ErikE/nSLua/3/

归功于 @ErikE ,以改善/减少原始代码,以帮助我实现冗余:)

答案 2 :(得分:3)

var foods = [
    {food: 'apple', type: 'fruit'},
    {food: 'potato', type: 'vegetable'},
    {food: 'banana', type: 'fruit'}
];

var newFoods = _.chain( foods ).reduce(function( memo, food ) {
  memo[ food.type ] = memo[ food.type ] || [];
  memo[ food.type ].push( food.food );
  return memo;
}, {}).map(function( foods, type ) {
    return {
        type: type,
        foods: foods
    };
}).value();

http://jsbin.com/etaxih/2/edit

答案 3 :(得分:2)

解决这个老问题的ES6解决方案:

使用Array#reduce进行迭代,并按组收集项目到Map。使用spread将Map#values转换回数组:

&#13;
&#13;
const data = [
    {food: 'apple', type: 'fruit'},
    {food: 'potato', type: 'vegetable'},
    {food: 'banana', type: 'fruit'},
];

const result = [...data.reduce((hash, { food, type }) => {
  const current = hash.get(type) || { type, foods: [] };
  
  current.foods.push({ food });
  
  return hash.set(type, current);
}, new Map).values()];

console.log(result);
&#13;
&#13;
&#13;

答案 4 :(得分:0)

您可以使用Alasql库的一个字段对对象数组进行分组。这个示例紧凑的数组与您的示例完全相同:

var res = alasql('SELECT type, ARRAY(food) AS foods FROM ? GROUP BY type',[food]);

试试这个例子at jsFiddle

答案 5 :(得分:0)

您还可以使用其他ES6功能,例如:

function groupArray(arr, groupBy, keepProperty) {
        let rArr = [], i;
        arr.forEach(item => {
            if((i = rArr.findIndex(obj => obj[groupBy] === item[groupBy])) !== -1)
                rArr[i][`${keepProperty}s`].push(item[keepProperty]);
            else rArr.push({
                [groupBy]: item[groupBy],
                [`${keepProperty}s`]: [item[keepProperty]]
            });
        });
        return rArr;
    }

    groupArray(yourArray, 'type', 'food');