我的数组是这样的:
myArray = [
{group: "one", color: "red"},
{group: "two", color: "blue"},
{group: "one", color: "green"},
{group: "one", color: "black"}
]
Run Code Online (Sandbox Code Playgroud)
我想将其转换为:
myArray = [
{group: "one", color: ["red", "green", "black"]}
{group: "two", color: ["blue"]}
]
Run Code Online (Sandbox Code Playgroud)
所以,基本上,分组group.
我尝试着:
for (i in myArray){
var group = myArray[i].group;
//myArray.push(group, {???})
}
Run Code Online (Sandbox Code Playgroud)
我只是不知道如何处理类似组值的分组.
198*_*983 69
首先创建组名到值的映射.然后转换为您想要的格式.
var myArray = [
{group: "one", color: "red"},
{group: "two", color: "blue"},
{group: "one", color: "green"},
{group: "one", color: "black"}
];
var group_to_values = myArray.reduce(function (obj, item) {
obj[item.group] = obj[item.group] || [];
obj[item.group].push(item.color);
return obj;
}, {});
var groups = Object.keys(group_to_values).map(function (key) {
return {group: key, color: group_to_values[key]};
});
var pre = document.createElement("pre");
pre.innerHTML = "groups:\n\n" + JSON.stringify(groups, null, 4);
document.body.appendChild(pre);Run Code Online (Sandbox Code Playgroud)
使用诸如reduce和map之类的Array实例方法为您提供了强大的高级构造,可以为您节省手动循环的痛苦.
neu*_*aut 27
首先,在JavaScript中,使用迭代数组通常不是一个好主意for ... in.看看为什么在数组迭代中使用"for ... in"是一个坏主意?详情.
所以你可能会尝试这样的事情:
var groups = {};
for (var i = 0; i < myArray.length; i++) {
var groupName = myArray[i].group;
if (!groups[groupName]) {
groups[groupName] = [];
}
groups[groupName].push(myArray[i].color);
}
myArray = [];
for (var groupName in groups) {
myArray.push({group: groupName, color: groups[groupName]});
}
Run Code Online (Sandbox Code Playgroud)
在groups这里使用中间对象有助于加快速度,因为它允许您避免嵌套循环来搜索数组.此外,因为groups是一个对象(而不是一个数组)迭代它使用for ... in是合适的.
附录
FWIW,如果要避免在结果数组中出现重复的颜色条目,可以if在行上方添加一个语句groups[groupName].push(myArray[i].color);以防止重复.使用jQuery看起来像这样;
if (!$.inArray(myArray[i].color, groups[groupName])) {
groups[groupName].push(myArray[i].color);
}
Run Code Online (Sandbox Code Playgroud)
如果没有jQuery,你可能想要添加一个与jQuery相同的函数inArray:
Array.prototype.contains = function(value) {
for (var i = 0; i < this.length; i++) {
if (this[i] === value)
return true;
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
然后像这样使用它:
if (!groups[groupName].contains(myArray[i].color)) {
groups[groupName].push(myArray[i].color);
}
Run Code Online (Sandbox Code Playgroud)
请注意,在任何一种情况下,由于所有额外的迭代,您将减慢一些速度,所以如果您不需要避免结果数组中的重复颜色条目,我建议避免使用这些额外的代码.那里
使用lodash的groupby方法
创建一个对象,该对象由通过iteratee运行集合的每个元素的结果生成的键组成.分组值的顺序由它们在集合中出现的顺序确定.每个键的对应值是负责生成密钥的元素数组.使用一个参数调用iteratee :( value).
因此,使用lodash,您可以在一行中获得所需的内容.见下文
let myArray = [
{group: "one", color: "red"},
{group: "two", color: "blue"},
{group: "one", color: "green"},
{group: "one", color: "black"},
]
let grouppedArray=_.groupBy(myArray,'group')
console.log(grouppedArray)Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>Run Code Online (Sandbox Code Playgroud)
一种选择是:
var res = myArray.reduce(function(groups, currentValue) {
if ( groups.indexOf(currentValue.group) === -1 ) {
groups.push(currentValue.group);
}
return groups;
}, []).map(function(group) {
return {
group: group,
color: myArray.filter(function(_el) {
return _el.group === group;
}).map(function(_el) { return _el.color; })
}
});
Run Code Online (Sandbox Code Playgroud)
除了使用两遍方法的给定方法之外,如果找到新组,您还可以通过推送该组来采取单循环方法。
var array = [{ group: "one", color: "red" }, { group: "two", color: "blue" }, { group: "one", color: "green" }, { group: "one", color: "black" }],
groups = Object.create(null),
grouped = [];
array.forEach(function (o) {
if (!groups[o.group]) {
groups[o.group] = [];
grouped.push({ group: o.group, color: groups[o.group] });
}
groups[o.group].push(o.color);
});
console.log(grouped);Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper { max-height: 100% !important; top: 0; }Run Code Online (Sandbox Code Playgroud)
使用 ES6,这可以很好地使用.reduce()aMap作为累加器,然后使用Array.from()其映射函数将每个分组的映射条目映射到一个对象:
const arr = [{"group":"one","color":"red"},{"group":"two","color":"blue"},{"group":"one","color":"green"},{"group":"one","color":"black"}];
const res = Array.from(arr.reduce((m, {group, color}) =>
m.set(group, [...(m.get(group) || []), color]), new Map
), ([group, color]) => ({group, color})
);
console.log(res);Run Code Online (Sandbox Code Playgroud)
如果您的对象中除了groupand之外还有其他属性color,您可以采用更通用的方法,将分组对象设置为地图的值,如下所示:
const arr = [{"group":"one","color":"red"},{"group":"two","color":"blue"},{"group":"one","color":"green"},{"group":"one","color":"black"}];
const groupAndMerge = (arr, groupBy, mergeInto) =>
Array.from(arr.reduce((m, o) => {
const curr = m.get(o[groupBy]);
return m.set(o[groupBy], {...o, [mergeInto]: [...(curr && curr[mergeInto] || []), o[mergeInto]]});
}, new Map).values());
console.log(groupAndMerge(arr, 'group', 'color'));Run Code Online (Sandbox Code Playgroud)
如果您可以支持可选链接和空合并运算符 (??),则可以将上述方法简化为以下内容:
const arr = [{"group":"one","color":"red"},{"group":"two","color":"blue"},{"group":"one","color":"green"},{"group":"one","color":"black"}];
const groupAndMerge = (arr, groupBy, mergeWith) =>
Array.from(arr.reduce((m, o) => m.set(o[groupBy], {...o, [mergeWith]: [...(m.get(o[groupBy])?.[mergeWith] ?? []), o[mergeWith]]}), new Map).values());
console.log(groupAndMerge(arr, 'group', 'color'));Run Code Online (Sandbox Code Playgroud)