1

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: '[email protected]', Points: 33},
        {Name: 'Doug', email: '[email protected]', Points: 12}
    ],
    [
        {Name: 'Josh', email: '[email protected]', Points: 11},
        {Name: 'Doug', email: '[email protected]', Points: 18}
    ],
    [
        {Name: 'Josh', email: '[email protected]', Points: 2},
        {Name: 'Doug', email: '[email protected]', 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:

[
    {Name: 'Josh', email: '[email protected]', Points: [33, 11, 2]},
    {Name: 'Doug', email: '[email protected]', 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/

3
  • is the structure of these pre-determined or dynamic? Commented Oct 18, 2012 at 16:18
  • Do you need recursive flattening, or just one level? Are you using underscore.js or similar? Commented Oct 18, 2012 at 16:20
  • The structure is static. I do not need recursive flattening, and I'm not using any js libraries Commented Oct 18, 2012 at 16:48

2 Answers 2

2

Here's one way using .reduce() and .forEach(). (You'll need patches if you're supporting older browsers.)

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.

flat = [].concat.apply([], data);

This turns your data into this structure:

[{Name:"Josh", email:"[email protected]", Points:33},
 {Name:"Doug", email:"[email protected]", Points:12},
 {Name:"Josh", email:"[email protected]", Points:11},
 {Name:"Doug", email:"[email protected]", Points:18},
 {Name:"Josh", email:"[email protected]", Points:2},
 {Name:"Doug", email:"[email protected]", Points:27}]

And makes the consolidation a bit simpler by eliminating the need for the inner .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;
Sign up to request clarification or add additional context in comments.

Comments

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

http://jsfiddle.net/Qhxzz/2/

1 Comment

works fine, would be easier if the result was an object rather than an array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.