2013-01-04 116 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 +'';' –