I'm trying to take an array of many arrays that contain many objects and manipulate it into an array of objects.
我正在尝试获取包含许多对象的许多数组的数组,并将其操作为对象数组。
So, let's say I have an array that looks like this:
所以,假设我有一个看起来像这样的数组:
[
[
{Name: 'Josh', email: 'josh@gmail.com', Points: 33},
{Name: 'Doug', email: 'doug@gmail.com', Points: 12}
],
[
{Name: 'Josh', email: 'josh@gmail.com', Points: 11},
{Name: 'Doug', email: 'doug@gmail.com', Points: 18}
],
[
{Name: 'Josh', email: 'josh@gmail.com', Points: 2},
{Name: 'Doug', email: 'doug@gmail.com', Points: 27}
]
]
The Desired outcome would be an array of objects that has a 'Points' property to hold an array of the points. So it would look like this:
期望的结果将是一个对象数组,其具有'Points'属性来保存点的数组。所以它看起来像这样:
[
{Name: 'Josh', email: 'josh@gmail.com', Points: [33, 11, 2]},
{Name: 'Doug', email: 'doug@gmail.com', Points: [12, 18, 27]}
]
This problem seems simple, but I can't seem to figure out the best way of doing this. If you want this data in a fiddle, I made this for you to play with: http://jsfiddle.net/Qhxzz/1/
这个问题看似简单,但我似乎无法弄清楚这样做的最佳方法。如果你想把这些数据放在一个小提琴里,我就让你玩这个:http://jsfiddle.net/Qhxzz/1/
2 个解决方案
#1
2
Here's one way using .reduce()
and .forEach()
. (You'll need patches if you're supporting older browsers.)
这是使用.reduce()和.forEach()的一种方法。 (如果您支持旧版浏览器,则需要修补程序。)
var consolidated = data.reduce(function(holder, arr) {
arr.forEach(function(obj) {
if (obj.email in holder.emails)
holder.emails[obj.email].Points.push(obj.Points);
else {
holder.emails[obj.email] = obj;
holder.result.push(obj);
obj.Points = [obj.Points];
}
});
return holder;
}, {emails:{},result:[]}).result;
And actually, we could flatten out the original Array using concat.apply()
, and be left with one monolithic Array to iterate.
实际上,我们可以使用concat.apply()来展平原始数组,并留下一个单片阵列进行迭代。
flat = [].concat.apply([], data);
This turns your data
into this structure:
这会将您的数据转换为此结构:
[{Name:"Josh", email:"josh@gmail.com", Points:33},
{Name:"Doug", email:"doug@gmail.com", Points:12},
{Name:"Josh", email:"josh@gmail.com", Points:11},
{Name:"Doug", email:"doug@gmail.com", Points:18},
{Name:"Josh", email:"josh@gmail.com", Points:2},
{Name:"Doug", email:"doug@gmail.com", Points:27}]
And makes the consolidation a bit simpler by eliminating the need for the inner .forEach()
.
通过消除内部.forEach()的需要,使合并更简单一些。
var consolidated = flat.reduce(function(holder, obj) {
if (obj.email in holder.emails)
holder.emails[obj.email].Points.push(obj.Points);
else {
holder.emails[obj.email] = obj;
holder.result.push(obj);
obj.Points = [obj.Points];
}
return holder;
}, {emails:{}, result:[]}).result;
#2
2
Note that this depends on the input structure being static (no recursion here). Assuming you're not using any libraries:
请注意,这取决于输入结构是静态的(这里没有递归)。假设您没有使用任何库:
var result = [];
for (var i = 0; i < initial.length; i++) {
var innerArray = initial[i];
for (var j = 0; j < innerArray.length; j++) {
var item = innerArray[j];
var found = false;
// search result for an object with a matching email prop
for (var k = 0; k < result.length; k++) {
if (result[k].email === item.email) {
found = true;
// add this Point to the Points array
result[k].Points.push(item.Points);
}
}
if (!found) {
// convert Points to an array of Points
item.Points = [item.Points];
result.push(item);
}
}
}
#1
2
Here's one way using .reduce()
and .forEach()
. (You'll need patches if you're supporting older browsers.)
这是使用.reduce()和.forEach()的一种方法。 (如果您支持旧版浏览器,则需要修补程序。)
var consolidated = data.reduce(function(holder, arr) {
arr.forEach(function(obj) {
if (obj.email in holder.emails)
holder.emails[obj.email].Points.push(obj.Points);
else {
holder.emails[obj.email] = obj;
holder.result.push(obj);
obj.Points = [obj.Points];
}
});
return holder;
}, {emails:{},result:[]}).result;
And actually, we could flatten out the original Array using concat.apply()
, and be left with one monolithic Array to iterate.
实际上,我们可以使用concat.apply()来展平原始数组,并留下一个单片阵列进行迭代。
flat = [].concat.apply([], data);
This turns your data
into this structure:
这会将您的数据转换为此结构:
[{Name:"Josh", email:"josh@gmail.com", Points:33},
{Name:"Doug", email:"doug@gmail.com", Points:12},
{Name:"Josh", email:"josh@gmail.com", Points:11},
{Name:"Doug", email:"doug@gmail.com", Points:18},
{Name:"Josh", email:"josh@gmail.com", Points:2},
{Name:"Doug", email:"doug@gmail.com", Points:27}]
And makes the consolidation a bit simpler by eliminating the need for the inner .forEach()
.
通过消除内部.forEach()的需要,使合并更简单一些。
var consolidated = flat.reduce(function(holder, obj) {
if (obj.email in holder.emails)
holder.emails[obj.email].Points.push(obj.Points);
else {
holder.emails[obj.email] = obj;
holder.result.push(obj);
obj.Points = [obj.Points];
}
return holder;
}, {emails:{}, result:[]}).result;
#2
2
Note that this depends on the input structure being static (no recursion here). Assuming you're not using any libraries:
请注意,这取决于输入结构是静态的(这里没有递归)。假设您没有使用任何库:
var result = [];
for (var i = 0; i < initial.length; i++) {
var innerArray = initial[i];
for (var j = 0; j < innerArray.length; j++) {
var item = innerArray[j];
var found = false;
// search result for an object with a matching email prop
for (var k = 0; k < result.length; k++) {
if (result[k].email === item.email) {
found = true;
// add this Point to the Points array
result[k].Points.push(item.Points);
}
}
if (!found) {
// convert Points to an array of Points
item.Points = [item.Points];
result.push(item);
}
}
}