2012-10-18 127 views
1

我試圖獲取包含許多對象的許多數組的數組,並將其操作爲對象數組。將許多數組合併成一個數組(JavaScript)

所以,讓我們說我有一個數組,看起來像這樣:

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

期望的結果將是對象的數組,有一個「點」屬性以保存點的數組。所以它看起來是這樣的:

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

這個問題看起來很簡單,但我似乎無法弄清楚這樣做的最佳方式。如果你想把這個數據放在小提琴裏,我就讓你玩這個:http://jsfiddle.net/Qhxzz/1/

+0

是這些預定義或動態的結構嗎? – jbabey

+0

你需要遞歸展平還是隻有一個層次?你使用的是underscore.js還是類似的? – singpolyma

+0

結構是靜態的。我不需要遞歸拼合,並且我沒有使用任何js庫 – frshca

回答

2

下面是使用.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; 

而實際上,我們可以拉平使用concat.apply()原陣列,並用一個單片陣列留給迭代。

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

這就使你的data成這種結構:

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

,使合併通過消除內.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; 
+1

+1,非常好的方法。 – raina77ow

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/

+0

工作正常,如果結果是一個對象而不是數組會更容易。 – Christoph

相關問題