Javascript | Группирование объектов
У меня есть объект. Он выглядит следующим образом:
[
{
"name":"Display",
"group":"Technical detals",
"id":"60",
"value":"4"
},
{
"name":"Manufacturer",
"group":"Manufacturer",
"id":"58",
"value":"Apple"
},
{
"name":"OS",
"group":"Technical detals",
"id":"37",
"value":"Apple iOS"
}
]
Я хотел бы сгруппировать эти данные по полю группы и получить этот объект:
var obj = {
0 = [
{
'group' = 'Technical detals',
'name' = 'Display',
'id' = '60',
'value' = '4'
},
{
'group' = 'Technical detals',
'name' = 'OS',
'id' = '37',
'value' = 'Apple iOS'
}],
1 = [
{
'group' = 'Manufacturer',
'name' = 'Manufacturer',
'id' = '58',
'value' = 'Apple'
}]
}
Как я могу сгруппировать свой первый объект?
Ответы
Ответ 1
Попробуйте что-то вроде этого:
function groupBy(collection, property) {
var i = 0, val, index,
values = [], result = [];
for (; i < collection.length; i++) {
val = collection[i][property];
index = values.indexOf(val);
if (index > -1)
result[index].push(collection[i]);
else {
values.push(val);
result.push([collection[i]]);
}
}
return result;
}
var obj = groupBy(list, "group");
Имейте в виду, что Array.prototype.indexOf
не определен в IE8 и старше, но для этого существуют общие полисы.
Ответ 2
Если вы используете underscore.js в своем приложении, вы можете просто сделать следующее:
var groups = _.groupBy(data, 'group'); // data is your initial collection
Или, если вы предпочитаете не использовать какую-либо библиотеку, вы можете сделать это самостоятельно:
var groups = { };
data.forEach(function(item){
var list = groups[item.group];
if(list){
list.push(item);
} else{
groups[item.group] = [item];
}
});
Вы можете увидеть оба примера в действии http://jsfiddle.net/nkVu6/3/
Ответ 3
Вы можете использовать хеш-таблицу для групп и Array#forEach
для итерации массива.
Затем проверьте, существует ли хеш, а если нет, присвойте ему пустой массив и отправьте его в набор результатов.
Позже вставьте фактический элемент в массив хэша.
function groupBy(array, group) {
var hash = Object.create(null),
result = [];
array.forEach(function (a) {
if (!hash[a[group]]) {
hash[a[group]] = [];
result.push(hash[a[group]]);
}
hash[a[group]].push(a);
});
return result;
}
var data = [{ name: "Display", group: "Technical detals", id: 60, value: 4 }, { name: "Manufacturer", group: "Manufacturer", id: 58, value: "Apple" }, { name: "OS", group: "Technical detals", id: 37, value: "Apple iOS" }];
console.log(groupBy(data, "group"));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Ответ 4
Если вам нравится работать с ES6 Map
, то это для вас:
function groupBy(arr, prop) {
const map = new Map(Array.from(arr, obj => [obj[prop], []]));
arr.forEach(obj => map.get(obj[prop]).push(obj));
return Array.from(map.values());
}
const data = [{ name: "Display", group: "Technical detals", id: 60, value: 4 }, { name: "Manufacturer", group: "Manufacturer", id: 58, value: "Apple" }, { name: "OS", group: "Technical detals", id: 37, value: "Apple iOS" }];
console.log(groupBy(data, "group"));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Ответ 5
Reduce отлично подходит для подобных ситуаций. Ниже приведен list
ваших входных данных:
const list = [{
'name': 'Display',
'group': 'Technical detals',
'id': '60',
'value': '4'
},
{
'name': 'Manufacturer',
'group': 'Manufacturer',
'id': '58',
'value': 'Apple'
},
{
'name': 'OS',
'group': 'Technical detals',
'id': '37',
'value': 'Apple iOS'
}
];
const groups = list.reduce((groups, item) => {
const group = (groups[item.group] || []);
group.push(item);
groups[item.group] = group;
return groups;
}, {});
console.log(groups);
Ответ 6
Если вы используете lodash, вы можете использовать groupBy
.
Он поддерживает как массив, так и объект.
Пример:
_.groupBy([6.1, 4.2, 6.3], Math.floor);
// => { '4': [4.2], '6': [6.1, 6.3] }
// The `_.property` iteratee shorthand.
_.groupBy(['one', 'two', 'three'], 'length');
// => { '3': ['one', 'two'], '5': ['three'] }
Ответ 7
Я попытался использовать ответ, помеченный как принятый, но заметил, что в некоторых группах отсутствуют элементы, в зависимости от типа оцениваемого свойства. Это решение, полученное из этого ответа:
function groupBy(collection, property) {
var i = 0, values = [], result = [];
for (i; i < collection.length; i++) {
if(values.indexOf(collection[i][property]) === -1) {
values.push(collection[i][property]);
result.push(collection.filter(function(v) { return v[property] === collection[i][property] }));
}
}
return result;
}
var obj = groupBy(list, "group");
Ответ 8
Пытаться
let g = (d,h={},r={},i=0)=>(d.map(x=>(y=x.group,h[y]?1:(h[y]=++i,r[h[y]-1]=[]),r[h[y]-1].push(x))),r);
console.log( g(data) );
let data=[
{
"name":"Display",
"group":"Technical detals",
"id":"60",
"value":"4"
},
{
"name":"Manufacturer",
"group":"Manufacturer",
"id":"58",
"value":"Apple"
},
{
"name":"OS",
"group":"Technical detals",
"id":"37",
"value":"Apple iOS"
}
];
let g = (d,h={},r={},i=0)=>(d.map(x=>(y=x.group,h[y]?1:(h[y]=++i,r[h[y]-1]=[]),r[h[y]-1].push(x))),r);
console.log(g(data));