Clay Banks
Clay Banks

Reputation: 4581

Create a Map of Objects from an Array via Lodash

I have the following array of arrays consisting of a name, age, and department

[[ "Kevin", 22,"Psychology" ],
[ "Cathy", 26, "Psychology" ],
[ "David", 31, "Engineering" ],
[ "Christine", 23, "Engineering" ]]

I want to create a map based on the unique departments that would look like this:

{ Psychology: [ 
  { name: "Cathy", age: 26 }, 
  { name: "Kevin", age: 22 } ] 
},
{ Engineering: [ 
  { name: "Christine", age: 23 }, 
  { name: "David", age: 31 } ] 
}

The index of department in the array will always be same. How can this be done utilizing lodash?

Upvotes: 1

Views: 2267

Answers (2)

Scott Sauyet
Scott Sauyet

Reputation: 50797

Here is a lodash solution:

const {flow, groupBy, nth, mapValues, map, zipObject} = _

const transform = flow(
  people => groupBy(people, p => nth(p, 2)),
  grouped => mapValues(grouped, dept => map(
    dept, 
    person => zipObject(['name', 'age'], person)
  ))
)

const people = [["Kevin", 22, "Psychology"], ["Cathy", 26, "Psychology"], ["David", 31, "Engineering"], ["Christine", 23, "Engineering"]]

console.log(transform(people))
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>

It would probably be made simpler with lodash/fp, but I've never gotten that working correctly. I probably haven't spent much time on it because I'm one of the authors of another FP library for JS, Ramda. The solution above was created by translating my first code, written with Ramda:

const {pipe, groupBy, nth, map, zipObj} = R;

const transform = pipe(
  groupBy(nth(2)),
  map(map(zipObj(['name', 'age'])))
)

const people = [["Kevin", 22, "Psychology"], ["Cathy", 26, "Psychology"], ["David", 31, "Engineering"], ["Christine", 23, "Engineering"]]

console.log(transform(people))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>

I'm guessing that lodash/fp code would probably look pretty similar, except that you'd have to replace the first map with mapValues.

Upvotes: 1

Keith
Keith

Reputation: 24191

Without using a external library, using new ESNext stuff like this is pretty easy.

const data = [
[ "Kevin", 22,"Psychology" ],
[ "Cathy", 26, "Psychology" ],
[ "David", 31, "Engineering" ],
[ "Christine", 23, "Engineering" ]];

const result = data.reduce((a, v) => {
  const [name,age,dept] = v; 
  (a[dept] = a[dept] || []).push({name,age});
  return a;
}, {});

console.log(result);

Upvotes: 4

Related Questions