これを変換する方法:
[
{food: 'Apple', type: 'fruit'},
{food: 'potato', type: 'vegetable'},
{food: 'banana', type: 'fruit'},
]
これに:
[
{type: 'fruit', foods: ['Apple', 'banana']},
{type: 'vegetable', foods: ['potato']}
]
javaScriptまたはアンダースコアを使用
元のリストがlist
という名前の変数に含まれていると仮定します。
_
.chain(list)
.groupBy('type')
.map(function(value, key) {
return {
type: key,
foods: _.pluck(value, 'food')
}
})
.value();
アンダースコアを使用しない場合:
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));
デモ:http://jsfiddle.net/ErikE/nSLua/3/
クレジットは@ ErikEになります。元のコードを改善/削減して、冗長性を支援しました:)
ここに、@ Ianの答えの少し異なるがより一般的なバージョンがあります
警告:結果はOPの要件とわずかに異なりますが、この質問につまずく私のような他の人は、より一般的な答えIMHOの恩恵を受ける可能性があります
var origArr = [
{food: 'Apple', type: 'fruit'},
{food: 'potato', type: 'vegetable'},
{food: 'banana', type: 'fruit'}
];
function groupBy(arr, key) {
var newArr = [],
types = {},
newItem, i, j, cur;
for (i = 0, j = arr.length; i < j; i++) {
cur = arr[i];
if (!(cur[key] in types)) {
types[cur[key]] = { type: cur[key], data: [] };
newArr.Push(types[cur[key]]);
}
types[cur[key]].data.Push(cur);
}
return newArr;
}
console.log(groupBy(origArr, 'type'));
jsfiddle here を見つけることができます
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();
この古い質問に対するES6ソリューション:
Array#reduce
を使用して反復し、グループごとに項目を収集して Map
にします。 spreadを使用して、 Map#values
を配列に戻します:
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);
次のような他の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');
Alasqlライブラリを使用して、フィールドの1つでオブジェクトの配列をグループ化できます。この例では、例のとおりに配列を圧縮します。
var res = alasql('SELECT type, ARRAY(food) AS foods FROM ? GROUP BY type',[food]);
この例を試してください at jsFiddle 。