2012-11-13 35 views
9

在JavaScript中我試圖對象的數組類似的鍵轉換對象:如何轉在underscorejs

[{'a':1,'b':2}, {'a':3,'b':4}, {'a':5,'b':6,'c':7}] 

將物體與值的每個鍵的數組:

{'a':[1,3,5], 'b':[2,4,6], 'c':[7]}; 

使用underscore.js 1.4.2。

我在下面有一些工作代碼,但感覺比寫嵌套for循環感覺更長和更笨拙。

在下劃線中是否有更優雅的方式來做到這一點?有沒有簡單的我失蹤?

console.clear(); 

var input = [{'a':1,'b':2},{'a':3,'b':4},{'a':5,'b':6,'c':7}]; 
var expected = {'a':[1,3,5], 'b':[2,4,6], 'c':[7]}; 

// Ok, go 
var output = _(input) 
.chain() 
// Get all object keys 
.reduce(function(memo, obj) { 
    return memo.concat(_.keys(obj)); 
}, []) 
// Get distinct object keys 
.uniq() 
// Get object key, values 
.map(function(key) { 
    // Combine key value variables to an object 
    // ([key],[[value,value]]) -> {key: [value,value]} 
    return _.object(key,[ 
     _(input) 
     .chain() 
     // Get this key's values 
     .pluck(key) 
     // Filter out undefined 
     .compact() 
     .value() 
    ]); 
}) 
// Flatten array of objects to a single object 
// [{key1: [value]}, {key2, [values]}] -> {key1: [values], key2: [values]} 
.reduce(function(memo, obj) { 
    return _.extend(memo, obj); 
}, {}) 
.value(); 

console.log(output); 
console.log(expected); 
console.log(_.isEqual(output, expected)); 

感謝

回答

8

聽起來像是你想zip的對象。這將是對象analogous方法:

_.transpose = function(array) { 
    var keys = _.union.apply(_, _.map(array, _.keys)), 
     result = {}; 
    for (var i=0, l=keys.length; i<l; i++) { 
     var key = keys[i]; 
     result[key] = _.pluck(array, key); 
    } 
    return result; 
}; 

不過,我只想用

_.transpose = function(array) { 
    var result = {}; 
    for (var i=0, l=array.length; i<l) 
     for (var prop in array[i]) 
      if (prop in result) 
       result[prop].push(array[i][prop]); 
      else 
       result[prop] = [ array[i][prop] ]; 
    return result; 
}; 

沒有任何下劃線,在所有:-)當然,你可以使用一些方法迭代器,它可能然後看起來像

_.reduce(array, function(map, obj) { 
    return _.reduce(obj, function(map, val, key) { 
     if (key in map) 
      map[key].push(val) 
     else 
      map[key] = [val]; 
     return map; 
    }, map); 
}, {}); 
+0

啊,謝謝。其實,這不是我唯一的錯誤: -/ – Bergi

+0

@Bergi:非常感謝你的全面。你介意我是否在下劃線的github上打開一張包含轉置功能的票,並以你的答案爲例? –

+0

哦,嵌套減少是我想寫的東西,我想。 –

0

您需要3行lodash的:

_.merge.apply(null, _.union([{}], myArrayOfObjects, [function (a, b) { 
    return _.compact(_.flatten([a, b])); 
}])) 

有關的功能是什麼的詳細信息,請參閱the docs of _.merge