使用对象分组数组项目

我的数组是这样的:

myArray = [ {group: "one", color: "red"} {group: "two", color: "blue"} {group: "one", color: "green"} {group: "one", color: "black"} ] 

我想将其转换为:

 myArray = [ {group: "one", color: ["red", "green", "black"]} {group: "two", color: ["blue"]} ] 

所以,基本上是一个一个的group

我尝试着:

 for (i in myArray){ var group = myArray[i].group; //myArray.push(group, {???}) } 

我只是不知道如何处理类似团体价值的分组。

首先,在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]}); } 

在这里使用中介groups对象有助于加快速度,因为它可以避免嵌套循环来search数组。 此外,因为groups是一个对象(而不是一个数组)迭代它使用for ... in是适当的。

附录

FWIW,如果你想在结果数组中避免重复的颜色条目,你可以在行groups[groupName].push(myArray[i].color);之上添加if语句groups[groupName].push(myArray[i].color); 防止重复。 使用jQuery它看起来像这样;

 if (!$.inArray(myArray[i].color, groups[groupName])) { groups[groupName].push(myArray[i].color); } 

没有jQuery,你可能想添加一个和jQuery的inArray一样的inArray

 Array.prototype.contains = function(value) { for (var i = 0; i < this.length; i++) { if (this[i] === value) return true; } return false; } 

然后像这样使用它:

 if (!groups[groupName].contains(myArray[i].color)) { groups[groupName].push(myArray[i].color); } 

请注意,在任何情况下,由于所有额外的迭代,您都会慢一点,所以如果您不需要避免结果数组中出现重复的颜色条目,我build议避免使用这些额外的代码。 那里

首先创build组名到值的映射。 然后转换成你想要的格式。

 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); 

一种select是:

 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; }) } }); 

http://jsfiddle.net/dvgwodxq/

这个版本利用对象密钥是唯一的。 我们处理原始数组,并按照一个新对象的组来收集颜色。 然后从该组创build新的对象 – >颜色数组映射。

 var myArray = [{ group: "one", color: "red" }, { group: "two", color: "blue" }, { group: "one", color: "green" }, { group: "one", color: "black" }]; //new object with keys as group and //color array as value var newArray = {}; //iterate through each element of array myArray.forEach(function(val) { var curr = newArray[val.group] //if array key doesnt exist, init with empty array if (!curr) { newArray[val.group] = []; } //append color to this key newArray[val.group].push(val.color); }); //remove elements from previous array myArray.length = 0; //replace elements with new objects made of //key value pairs from our created object for (var key in newArray) { myArray.push({ 'group': key, 'color': newArray[key] }); } 

请注意,这不会考虑同一组的重复颜色,因此可能在单个组中使用相同颜色的多个颜色。

使用lodash的groupby方法

创build一个由运行集合中的每个元素到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) 
 <script src="ajax/libs/lodash.js/4.17.4/lodash.min.js"></script> 

你可以做这样的事情:

 function convert(items) { var result = []; items.forEach(function (element) { var existingElement = result.filter(function (item) { return item.group === element.group; })[0]; if (existingElement) { existingElement.color.push(element.color); } else { element.color = [element.color]; result.push(element); } }); return result; } 

除了采用双程方法的给定方法外,如果find新组,则可以通过推送组采用单循环方法。

 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); 
 .as-console-wrapper { max-height: 100% !important; top: 0; }