2013-01-04 165 views
3

我有一個如下所示的數組。根據公共值組合/合併數組中的對象

[ { sku: 'TEA-BLCK', price: '10', quantity: '1' }, 
    { sku: 'TEA-ELGY', price: '10', quantity: '1' }, 
    { sku: 'TEA-CHAI', price: '10', quantity: '1' }, 
    { sku: 'TEA-GREN', price: '10', quantity: '1' }, 
    { sku: 'TEA-ELGY', price: '10', quantity: '1' }, 
    { sku: 'TEA-MINT', price: '10', quantity: '1' } ] 

我需要使它看起來像這樣

[ { sku: 'TEA-BLCK', price: '10', quantity: '1' }, 
    { sku: 'TEA-ELGY', price: '10', quantity: '2' }, 
    { sku: 'TEA-CHAI', price: '10', quantity: '1' }, 
    { sku: 'TEA-GREN', price: '10', quantity: '1' }, 
    { sku: 'TEA-MINT', price: '10', quantity: '1' } ] 

我走到這一步,要使用underscore.jsreduce功能。

var reduce = function(){ 
    return _.reduce(line_items, function(quant, item) { 
     quant[item.sku] = (typeof(quant[item.sku]) !== "undefined") ? quant[item.sku] : 0 ; 
     quant[item.sku] = parseFloat(item.quantity) + quant[item.sku]; 
     return quant; 
    }, {}); 
} 

其中吐出以下內容。

{ 'TEA-BLCK': 1, 
    'TEA-ELGY': 1, 
    'TEA-CHAI': 2, 
    'TEA-GREN': 1, 
    'TEA-MINT': 1 } 

這是減少的好工作嗎?我怎樣才能以我想要的方式獲得它?

+3

'reduce'不太適合這項任務。考慮以'groupBy'和'map'開始。 – 2013-01-04 20:18:35

回答

3

嘗試這樣:

var line_items = [ 
    { sku: 'TEA-BLCK', price: '10', quantity: 2 }, 
    { sku: 'TEA-ELGY', price: '10', quantity: 3 }, 
    { sku: 'TEA-CHAI', price: '10', quantity: 1 }, 
    { sku: 'TEA-GREN', price: '10', quantity: 1 }, 
    { sku: 'TEA-ELGY', price: '10', quantity: 1 }, 
    { sku: 'TEA-MINT', price: '10', quantity: 1 } 
]; 

// Group items by sku. 
var line_items_by_sku = _(line_items).groupBy(function (item) { return item.sku; }); 

// Get the new line_items array based on the grouped data. 
line_items = _(line_items_by_sku).map(function (items) { 
    var item = items[0]; 
    item.quantity = _.reduce(items, function(memo, item){ return memo + item.quantity; }, 0); 
    return item; 
}); 

this jsfiddle

+0

太好了,謝謝 – ThomasReggi

+2

雖然初始數量不是1,但不起作用。 http://jsfiddle.net/xjUDY/2/ –

+0

非常真實。更新後的jsfiddle已經修復了,所以我換成了這個。謝謝! – benekastah

2

什麼這樣一個簡單的解決方案:

function reduce(array) { 
    var out = []; 
    var indexBySku = {}; 
    for (var i = array.length; i--;) { 
     if (!indexBySku[array[i].sku]) { 
      indexBySku[array[i].sku] = out.length; 
      out.push(array[i]); 
     } else { 
      out[indexBySku[array[i].sku]].quantity -= -array[i].quantity; 
     } 
    } 
    return out; 
} 

http://jsfiddle.net/waV6H/1

也許,這裏需要解釋是,我們減去的不是添加負行了嘛。這只是爲了避免字符串連接,因爲「數量」中的值是字符串。


超級壓縮版本,丟棄不需要的花括號和分號......只是爲了好玩。爲了保持和數量爲字符串,作品有量!= 1

function reduce(array) { 
    var out = [], indexBySku = {}, len = array.length, i, j 
    for (i = 0; i < len; i++) 
     (j = indexBySku[array[i].sku]) ? 
      out[j].quantity = out[j].quantity - -array[i].quantity + '' : 
      indexBySku[array[i].sku] = out.push(array[i]) - 1 
    return out 
} 
+0

此解決方案缺少具有SKU TEA-BLCK的項目。 – benekastah

+0

Derp,固定.... –

+0

感謝這! – ThomasReggi

1

我有點遲到了,但它聽起來很有趣,所以...

JSON.stringify(
[ { sku: 'TEA-BLCK', price: '10', quantity: '1' }, 
    { sku: 'TEA-ELGY', price: '10', quantity: '1' }, 
    { sku: 'TEA-CHAI', price: '10', quantity: '1' }, 
    { sku: 'TEA-GREN', price: '10', quantity: '1' }, 
    { sku: 'TEA-ELGY', price: '10', quantity: '1' }, 
    { sku: 'TEA-MINT', price: '10', quantity: '1' } ].sort(function (a, b) { 
    return a.sku < b.sku; 
}).reduce(function (a,v) { 
    if (!a[0] || a[0].sku !== v.sku ) { 
     a.unshift(v); 
    } else { 
     // notice the very inefficient str -> number -> str conversion 
     a[0].quantity = 1*a[0].quantity + 1*v.quantity + ''; 
    } 

    return a; 
}, [])); 

在這裏,我們預先對數組進行排序,然後將元素添加到累加器的開頭。 和GGG已經說過關於字符串。

http://jsfiddle.net/EqGUe/

+0

尼斯...功能性強,無依賴性,符合所有要求,適用於1以外的數量,將數量作爲字符串保存。不過,僅限ES5。 +1 –

+0

@GGG是的,但有了[es5shim](https://github.com/kriskowal/es5-shim),你甚至可以給IE6減少。 – c69

+0

我不認爲IE瀏覽器有數組#減少,直到像9 ...所以也許依賴關係畢竟;) –

1

晚了一點爲好,但有趣摸出 http://jsbin.com/amazat/2/

line_items_reduced = _.map(reduce(), function(value, key) { 
    var line_item = _.find(line_items, function(line_i){ 
    return (key === line_i.sku); 
    }); 
    line_item.quantity = value; 
    return line_item; 
}); 
+0

嗯爲什麼是'reduce'代碼丟失? ;) –

+0

與原始相同的代碼 –

1

這將更新benekastah的回答和處理量超過1 ... 但我冒昧將數量更改爲整數

http://jsfiddle.net/xjUDY/3/

var line_items = [ 
    { sku: 'TEA-BLCK', price: '10', quantity: 2 }, 
    { sku: 'TEA-ELGY', price: '10', quantity: 3 }, 
    { sku: 'TEA-CHAI', price: '10', quantity: 1 }, 
    { sku: 'TEA-GREN', price: '10', quantity: 1 }, 
    { sku: 'TEA-ELGY', price: '10', quantity: 1 }, 
    { sku: 'TEA-MINT', price: '10', quantity: 1 } 
]; 

// Group items by sku. 
var line_items_by_sku = _(line_items).groupBy(function (item) { return item.sku; }); 

// Get the new line_items array based on the grouped data. 
line_items = _(line_items_by_sku).map(function (items) { 
    var item = items[0]; 
    item.quantity = _.reduce(items, function(memo, item){ return memo + item.quantity; }, 0); 
    return item; 
}); 

document.write("<pre>"+JSON.stringify(line_items, null, " ")+"</pre>"); 
​ 
+1

即使在我的代碼中,永遠不會多於一個數量。我更喜歡這個。 – ThomasReggi

0

從技術上講,這是完整的答案。從字符串到字符串。對不起大家。

var line_items = [ 
    { sku: 'TEA-BLCK', price: '10', quantity: "2" }, 
    { sku: 'TEA-ELGY', price: '10', quantity: "3" }, 
    { sku: 'TEA-CHAI', price: '10', quantity: "1" }, 
    { sku: 'TEA-GREN', price: '10', quantity: "1" }, 
    { sku: 'TEA-ELGY', price: '10', quantity: "1" }, 
    { sku: 'TEA-MINT', price: '10', quantity: "1" } 
]; 

// Group items by sku. 
var line_items_by_sku = _(line_items).groupBy(function (item) { return item.sku; }); 

// Get the new line_items array based on the grouped data. 
line_items = _(line_items_by_sku).map(function (items) { 
    var item = items[0]; 
    item.quantity = _.reduce(items, function(memo, item){ return memo + parseFloat(item.quantity); }, 0); 
    item.quantity = item.quantity.toString(); 
    return item; 
}); 

document.write("<pre>"+JSON.stringify(line_items, null, " ")+"</pre>"); 
+0

爲什麼所有的parseFloat/toString的東西,而不僅僅是'返回備忘錄 - -item.quantity +'';' –