2
\$\begingroup\$

I have an array of objects where each object has two keys: key (k) and value (v). I need to make an object that would take values of k and collect corresponding values of v as a value of this key, an array of them.

So, for example, from an array

[{
  k: 'a',
  v: 0
}, {
  k: 'a',
  v: 1
}, {
  k: 'b',
  v: 2
}]

I need an object

{
  a: [0, 1],
  b: [2]
}

It's easy to use outer-scope variables but what I want to do is to perform it in functional manner.

Right now, I have this piece of (ES6) code:

rows.reduce((result, item) => ({
  ...result,
  [item.k]: [
    ...(result[item.k] || []),
    item.v
  ]}),
{});

It works nice but the question is if it is possible to optimize it in terms of SLOC. For one, I don't like the ...(result[item.k] || []) piece but if I leave it as simple as ...result[item.k] then I get an error because, when it's undefined, babel fails to perform a method call of it, since undefined doesn't have any methods.

Did I maybe take a wrong path and there's a more elegant solution that reducing the array?

I would appreciate any suggestions, please throw any ideas at me.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Btw, object spread is ES7, not ES6. \$\endgroup\$
    – Pavlo
    Commented Dec 8, 2015 at 13:38

2 Answers 2

5
\$\begingroup\$

We've got a readability issue here. This is the horror we all have to face when we overuse the new "concise" ES6 syntax. I had to read the code at least 3 times to understand what it was doing (and forgot ... is spread).

If you're worried about code size, let the minifier do its job. Code is for programmers to understand. The verbose version of it isn't that bad. It's not like it's not going to run in older browsers.

var result = rows.reduce(function(result, item){
  result[item.k] = (result[item.k] || []).concat(item);
  return result;
}, {});
\$\endgroup\$
0
3
\$\begingroup\$

If you are a fan of FP, you should use a functional library, e. g. Ramda. With it, you can create your transforming function points-free style:

import { compose, mapObj, map, prop, groupBy } from 'ramda';

const f = compose(
  mapObj(
    map(prop('v'))
  ),
  groupBy(prop('k'))
);

Proof: http://jsfiddle.net/03m7r7be/

\$\endgroup\$
1
  • \$\begingroup\$ If you like this answer most, you should accept it (there is a button to the left). \$\endgroup\$
    – Pavlo
    Commented Dec 9, 2015 at 13:17

Not the answer you're looking for? Browse other questions tagged or ask your own question.