Code Review Stack Exchange is a question and answer site for peer programmer code reviews. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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.

share|improve this question
1  
Btw, object spread is ES7, not ES6. – Pavlo Dec 8 '15 at 13:38

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;
}, {});
share|improve this answer
    
This solution was among the easiest I'd come up with, but it's not "pure functional", imho. I'm kinda mad about FP, sorry. – Rishat Muhametshin Dec 4 '15 at 18:42

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/

share|improve this answer
    
OMG SO CLEAN! Thanks a lot, I should have definitely taken a closer look at Ramda. In fact, I know about this library, but I've never considered using it against lodash or simply those cool new ES6 features. – Rishat Muhametshin Dec 8 '15 at 22:10
    
If you like this answer most, you should accept it (there is a button to the left). – Pavlo Dec 9 '15 at 13:17

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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