1

多くのオブジェクトを含む多くの配列の配列を取得し、それをオブジェクトの配列に操作しようとしています。

それで、私がこのような配列を持っているとしましょう:

[
    [
        {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}
    ]
]​

望ましい結果は、ポイントの配列を保持するための「Points」プロパティを持つオブジェクトの配列になります。したがって、次のようになります。

[
    {Name: 'Josh', email: 'josh@gmail.com', Points: [33, 11, 2]},
    {Name: 'Doug', email: 'doug@gmail.com', Points: [12, 18, 27]}
]

この問題は単純に思えますが、これを行うための最良の方法を理解できないようです。このデータをフィドルに入れたい場合は、http://jsfiddle.net/Qhxzz/1/で試してみてください。

4

2 に答える 2

2

これは、静的な入力構造に依存することに注意してください(ここでは再帰はありません)。ライブラリを使用していないと仮定します。

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/

于 2012-10-18T16:28:38.147 に答える
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:"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().

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;
于 2012-10-18T16:42:22.077 に答える