我有这样一个沉重的阵列:
[
{Id: 1, Name: 'Red', optionName: 'Color'},
{Id: 2, Name: 'Yellow', optionName: 'Color'},
{Id: 3, Name: 'Blue', optionName: 'Color'},
{Id: 4, Name: 'Green', optionName: 'Color'},
{Id: 7, Name: 'Black', optionName: 'Color'},
{Id: 8, Name: 'S', optionName: 'Size'},
{Id: 11, Name: 'M', optionName: 'Size'},
{Id: 12, Name: 'L', optionName: 'Size'},
{Id: 13, Name: 'XL', optionName: 'Size'},
{Id: 14, Name: 'XXL', optionName: 'Size'}
]
我需要做的是按optionName
对它们进行分组,并在主数组中有两行,如下所示:
[
{
Name: 'Color',
Data:[{Id: 1, Name: 'Red'},
{Id: 2, Name: 'Yellow'},
{Id: 3, Name: 'Blue'},
{Id: 4, Name: 'Green'},
{Id: 7, Name: 'Black'}]
}, {
Name: 'Size',
Data:[{Id: 8, Name: 'S'},
{Id: 11, Name: 'M'},
{Id: 12, Name: 'L'},
{Id: 13, Name: 'XL'},
{Id: 14, Name: 'XXL'}]
}
]
如何在javascript中完成?
答案 0 :(得分:13)
这是我为这种情况写的一段摘录。您可以将此功能添加到所有阵列:
emit
你可以像这样使用它。您只需传递一个定义数据分组方式的函数即可。
Object.defineProperty(Array.prototype, 'group', {
enumerable: false,
value: function (key) {
var map = {};
this.forEach(function (e) {
var k = key(e);
map[k] = map[k] || [];
map[k].push(e);
});
return Object.keys(map).map(function (k) {
return {key: k, data: map[k]};
});
}
});
如果需要,可以将var newArray = arr.group(function (item) {
return item.optionName;
});
替换为{key: k, data: map[k]}
。
这也是上面代码更紧凑的ES6版本:
{Name: k, Data: map[k]}
像这样使用:
Object.defineProperty(Array.prototype, 'group', {
enumerable: false,
value: function (key) {
let map = {};
this.map(e => ({k: key(e), d: e})).forEach(e => {
map[e.k] = map[e.k] || [];
map[e.k].push(e.d);
});
return Object.keys(map).map(k => ({key: k, data: map[k]}));
}
});
答案 1 :(得分:3)
您可以使用reduce来获取所需的结果集:
var result = list.reduce(function(memo, item) {
if (item.optionName === 'Color') {
memo[0].Data.push(
Id: item.Id,
Name: item.Name
});
}
if (item.optionName === 'Size') {
memo[1].Data.push({
Id: item.Id,
Name: item.Name
});
}
return memo;
}, [{ Name: 'Color', Data: [] }, { Name: 'Size', Data: [] }]);
变量列表是您的第一个列表。
希望这有帮助。
答案 2 :(得分:3)
使用Map对象的ES6解决方案:
function groupBy(arr, key) {
return arr.reduce(
(sum, item) => {
const groupByVal = item[key];
groupedItems = sum.get(groupByVal) || [];
groupedItems.push(item);
return sum.set(groupByVal, groupedItems);
},
new Map()
);
}
var Data = [
{ Id: 1, Name: 'Red', optionName: 'Color' },
{ Id: 2, Name: 'Yellow', optionName: 'Color' },
{ Id: 3, Name: 'Blue', optionName: 'Color' },
{ Id: 4, Name: 'Green', optionName: 'Color' },
{ Id: 7, Name: 'Black', optionName: 'Color' },
{ Id: 8, Name: 'S', optionName: 'Size' },
{ Id: 11, Name: 'M', optionName: 'Size' },
{ Id: 12, Name: 'L', optionName: 'Size' },
{ Id: 13, Name: 'XL', optionName: 'Size' },
{ Id: 14, Name: 'XXL', optionName: 'Size' } ];
document.getElementById("showArray").innerHTML =JSON.stringify([...groupBy(Data, 'optionName')], null, 4);
<pre id="showArray"></pre>
答案 3 :(得分:1)
这是我在所有数组的应用程序功能中编写的一段代码。此代码段用于节点js应用程序。以上所有都给出了解决方案,但我在节点js的服务器端发现了一些问题。 这个片段是用户满满的......
var Data= [
{ Id: 1, Name: 'Red', optionName: 'Color' },
{ Id: 2, Name: 'Yellow', optionName: 'Color' },
{ Id: 3, Name: 'Blue', optionName: 'Color' },
{ Id: 4, Name: 'Green', optionName: 'Color' },
{ Id: 7, Name: 'Black', optionName: 'Color' },
{ Id: 8, Name: 'S', optionName: 'Size' },
{ Id: 11, Name: 'M', optionName: 'Size' },
{ Id: 12, Name: 'L', optionName: 'Size' },
{ Id: 13, Name: 'XL', optionName: 'Size' },
{ Id: 14, Name: 'XXL', optionName: 'Size' } ];
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;
}
我这样使用它。我只是传递一个函数,它定义了如何对数据进行分组。
filterData= groupBy(Data,'optionName');
此代码输出片段的结果.....
[
{"type":"Color","data":[{"Id":1,"Name":"Red","optionName":"Color"},
{"Id":2,"Name":"Yellow","optionName":"Color"},
{"Id":3,"Name":"Blue","optionName":"Color"},
{"Id":4,"Name":"Green","optionName":"Color"},
{"Id":7,"Name":"Black","optionName":"Color"}]},
{"type":"Size","data":[{"Id":8,"Name":"S","optionName":"Size"},
{"Id":11,"Name":"M","optionName":"Size"},
{"Id":12,"Name":"L","optionName":"Size"},
{"Id":13,"Name":"XL","optionName":"Size"},
{"Id":14,"Name":"XXL","optionName":"Size"}]}
]
答案 4 :(得分:0)
var originalList = [ { Id: 1, Name: 'Red', optionName: 'Color' },
{ Id: 2, Name: 'Yellow', optionName: 'Color' },
{ Id: 3, Name: 'Blue', optionName: 'Color' },
{ Id: 4, Name: 'Green', optionName: 'Color' },
{ Id: 7, Name: 'Black', optionName: 'Color' },
{ Id: 8, Name: 'S', optionName: 'Size' },
{ Id: 11, Name: 'M', optionName: 'Size' },
{ Id: 12, Name: 'L', optionName: 'Size' },
{ Id: 13, Name: 'XL', optionName: 'Size' },
{ Id: 14, Name: 'XXL', optionName: 'Size' } ];
var output = [{ Name: "Color", Data: [] },{ Name: "Size", Data: [] }] ;
originalList.map(function(entry){
if ( entry.optionName === "Color") output[0].Data.push({ Id: entry.Id, Name: entry.Name });
if ( entry.optionName === "Size") output[1].Data.push({ Id: entry.Id, Name: entry.Name });
});
答案 5 :(得分:0)
'use strict'
let l = [ { Id: 1, Name: 'Red', optionName: 'Color' },
{ Id: 2, Name: 'Yellow', optionName: 'Color' },
{ Id: 3, Name: 'Blue', optionName: 'Color' },
{ Id: 4, Name: 'Green', optionName: 'Color' },
{ Id: 7, Name: 'Black', optionName: 'Color' },
{ Id: 8, Name: 'S', optionName: 'Size' },
{ Id: 11, Name: 'M', optionName: 'Size' },
{ Id: 12, Name: 'L', optionName: 'Size' },
{ Id: 13, Name: 'XL', optionName: 'Size' },
{ Id: 14, Name: 'XXL', optionName: 'Size' } ];
let color = [];
let size = [];
l.forEach(element => {
if (element['optionName'] === 'Color') {
color.push({'Id': element.Id, 'Name': element.Name});
} else {
size.push({'Id': element.Id, 'Name': element.Name});
}
});
console.log(color);
console.log(size);
你可以尝试这种方法。
答案 6 :(得分:0)
所有答案都会导致相同的结果,所以这一切都归结为个人偏好(或公司指导方针)如何解决这个问题。
// ES5 (traditional javascript) version
function groupByOptionName(list, optionName) {
return list
// filter out any item whose optionName does not match the desired name
.filter(function(item) {
return item.optionName === optionName;
})
// map the item into the desired shape
// (appears to be everything except optionName itself
.map(function(item) {
return {
Id: item.Id,
Name: item.Name
};
})
}
// ES2015/ES6 version
function groupByOptionName(list, optionName) {
return list
// filter out any item whose optionName does not match the desired name
.filter(item => item.optionName === optionName)
// map the item into the desired shape
// (appears to be everything except optionName itself
.map(item => {
Id: item.Id,
Name: item.Name
});
}
此功能可让您按如下方式编写所需的结果:
var output = [
{Name: 'Color', Data: groupByOptionName(list, 'Color')},
{Name: 'Size', Data: groupByOptionName(list, 'Size')},
];
// the ES2015/ES6 version of this code would replace var with let
虽然代码本身不同,但它与其他答案非常相似,只需对所需步骤进行修改。
还可以选择通过提取所有硬编码选项名称(Color
和Size
),这样可以提供更动态的输入,但也可以引入更多实际需要的处理
// ES5 (traditional javascript) version
function getOptionNames(list) {
return list
// map the array into a list of optionNames
.map(function(item) {
return item.optionName;
})
// remove duplicates
.filter(function(item, index, all) {
return all.indexOf(item) === index;
});
}
// ES2015/ES6 version (does exactly the same as the one above)
function getOptionNames(list) {
return list
// map the array into a list of optionNames
.map(item => item.optionName)
// remove duplicates
.filter((item, index, all) => all.indexOf(item) === index);
}
这允许结果完全基于输入数据:
// ES5 (traditional javascript) version
var output = getOptionNames(list)
// map the names into the desired structure
.map(function(buffer, name) {
return {
Name: name,
Data: groupByOptionName(list, name)
};
});
// ES2015/ES6 version (does exactly the same as the one above)
var output = getOptionNames(list)
// map the names into the desired structure
.map((buffer, name) => {
Name: name,
Data: groupByOptionName(list, name)
});
通过简短的步骤编写所有数据修改步骤,如果需要调整此代码,您可以自己做(特别是未来的自己)。
如果数据集确实很重(就很多数据而言),您还必须确保保留在内存中的副本数量有限。例如,如果您从不需要原始数据集,请确保它可以被垃圾收集(通过在接收数据的范围之外没有包含它的变量)
答案 7 :(得分:0)
<强>用法:强>
groupValues([
{ color: 'blue', value: 100 },
{ color: 'blue', value: 75 },
{ color: 'yellow', value: 50 },
{ color: 'yellow', value: 25 }
], 'color')
<强>结果:强>
[
[{ color: 'blue', value: 100 }, { color: 'blue', value: 75 }],
[{ color: 'yellow', value: 50 }, { color: 'yellow', value: 25 }]
]
<强>功能:强>
const groupValues = function(arr, key) {
const mapped = {}
arr.forEach(el => {
const actualKey = el[key]
if(!mapped.hasOwnProperty(actualKey)) mapped[actualKey] = []
mapped[actualKey].push(el)
})
return Object.keys(mapped).map(el => mapped[el])
}