Search code examples
arrayscoffeescriptsum

Merge values of an array and sum duplicate values


I know there are a couple solutions out there for vanilla JS but I can't seem to make these work within Framer's Coffeescript.

I am trying to loop through an array of nested arrays and combine duplicate values of the first item of the nested array while adding the values of the second item.

So for example the following array will be consolidated into a single

fruit = [
  ["bananas", 2],
  ["apples", 1],
  ["oranges", 2],
  ["bananas", 1],
  ["oranges", 2],
  ["apples", 3]
]

Will result in the following:

combinedFruit = [
  ["bananas", 3],
  ["apples", 4],
  ["oranges", 4]
]

Solution

  • The usual approach to this sort of thing is to use an object to keep track of your sums:

    sum_fruit_counters = (obj, [fruit, n]) ->
      obj[fruit] = 0 if fruit !of obj
      obj[fruit] += n
      obj
    obj = fruit.reduce(sum_fruit_counters, { })
    

    or if you prefer:

    sum_fruit_counters = (obj, [fruit, n]) ->
      obj[fruit] = (obj[fruit] || 0) + n
      obj
    obj = fruit.reduce(sum_fruit_counters, { })
    

    But that leaves you with an object rather than the array of arrays you want. You could use Object.entries to take care of that:

    a = Object.entries(fruit.reduce(sum_fruit_counters, { }))
    

    or do it by hand with a simple loop:

    obj = fruit.reduce(sum_fruit_counters, { })
    a   = ([k, v] for k, v of obj)
    

    You could also use a loop instead of reduce, the logic would be pretty much the same.