最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - lodash, group and count - Stack Overflow

programmeradmin2浏览0评论

for array like this

[{ dep: 'A', qt: 10, price: 5},
 { dep: 'A', qt: 5,  price: 2.30 },
 { dep: 'B', qt: 3,  price: 2.20 },
 { dep: 'C', qt: 1,  price: 4 },
 { dep: 'C', qt: 4,  price: 10 }
 ...etc.. 
]

What's the elegant way to both group and sum values, resulting into:

[{ dep: 'A', qt: 15, price: 61.5 },
 { dep: 'B', qt: 3, price: 2.20 },
 { dep: 'C', qt: 5: price: 44 }
]

for array like this

[{ dep: 'A', qt: 10, price: 5},
 { dep: 'A', qt: 5,  price: 2.30 },
 { dep: 'B', qt: 3,  price: 2.20 },
 { dep: 'C', qt: 1,  price: 4 },
 { dep: 'C', qt: 4,  price: 10 }
 ...etc.. 
]

What's the elegant way to both group and sum values, resulting into:

[{ dep: 'A', qt: 15, price: 61.5 },
 { dep: 'B', qt: 3, price: 2.20 },
 { dep: 'C', qt: 5: price: 44 }
]
Share Improve this question edited Apr 12, 2014 at 2:06 mu is too short 435k71 gold badges858 silver badges818 bronze badges asked Apr 12, 2014 at 0:25 iLemmingiLemming 36.3k61 gold badges198 silver badges316 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 8

You could do something like this:

function sumInvoices(p, c) {
    return _.extend(p, {qt:p.qt + c.qt, price:p.price + c.qt*c.price});
};

var b = _(a)
  .groupBy('dep')
  .map(function(b) {return b.reduce(sumInvoices, {dep:b[0].dep, qt:0, price:0})})
  .valueOf();

I'd probably go straight to Array.prototype.reduce for something like this:

var b = a.reduce(function(cache, e) {
    var sum = cache.by_dep[e.dep];
    if(!sum) {
        sum = cache.by_dep[e.dep]
            = { dep: e.dep, qt: 0, price: 0 };
        cache.a.push(sum);
    }
    sum.qt    += e.qt;
    sum.price += e.price;
    return cache;
}, { by_dep: { }, a: [ ] }).a;

You want easy access by dep so you index your running totals by dep (by_dep: { }) but you also want an array at the end so store the same references in an array (a: [ ]). Then pull out the a cache at the end and you're done.

Demo: http://jsfiddle/ambiguous/T8jgx/

That's probably just as simple as a pipeline of Underscore/Lodash calls. But if you must use those libraries then you could _(a).reduce(...) instead of a.reduce(...).

2021's answer

You can use Array#reduce with the highest performance O(n) time plexity in this way:

const arr = [{ dep: 'A', qt: 10, price: 5},{ dep: 'A', qt: 5,  price: 2.30 },{ dep: 'B', qt: 3,  price: 2.20 },{ dep: 'C', qt: 1,  price: 4 },{ dep: 'C', qt: 4,  price: 10 }];
 
const result = arr.reduce((acc, {dep, qt, price}) => {
  acc[dep] ??= {dep, qt: 0, price: 0};
  
  acc[dep]["qt"]+= qt;
  acc[dep]["price"]+= (price * qt);
  return acc;
}, {});

console.log(Object.values(result));

发布评论

评论列表(0)

  1. 暂无评论