Stefan
Stefan

Reputation: 1071

How to convert an array of objects to an object in Lodash?

I have this:

[ 
  { list: [ [Object], [Object] ] },
  { head: [ [Object], [Object] ] }
]

And want to turn it into this:

{ 
  list: [ [Object], [Object] ],
  head: [ [Object], [Object] ]
}

So an array of objects into an object. It would be great to achieve this with lodash.

Upvotes: 20

Views: 28159

Answers (6)

Nelu
Nelu

Reputation: 18690

With TypeScript:

interface State {
  state: string;
  name: string;
}

const states: State[] = [
  { state: "NY", name: "New York" },
  { state: "AZ", name: "Arizona" },
];

const statesObj = reduce<State, Record<string, string>>(
  states,
  (memo, { state, name }) => assign(memo, { [state]: name }),
  {},
);

console.log(statesObj); // <-- {AZ: "Arizona"}, {NY: "New York"}

Upvotes: 0

Johannes Fahrenkrug
Johannes Fahrenkrug

Reputation: 44730

To build on @rcsole's great answer, this works well:

states = [{
  state: "NY",
  name: "New York",
}, {
  state: "AZ",
  name: "Arizona",
}]

statesObj = Object.assign({}, ...states.map(state => { 
  return { [state.state]: state.name } 
}))

Result:

{
  AZ: "Arizona",
  NY: "New York",
}

What's going on here?

Let's break this up into multiple pieces:

// Step 1: Transform from [{state: "Foo", name: "Bar"}, ...] to [{Foo: "Bar"}, ...]
mappedStates = states.map(state => { return { [state.state]: state.name } })

// Step 2: Merge all the objects in that array into a single new object
statesObj = Object.assign({}, ...mappedStates)

Step 1 uses map to iterate over every item in the array (every state object). map executes a function for every state object and returns a new object with the state as the key and the name as the value. We need to surround state.state in brackets because it's a dynamic value in an object literal.

Step 2 uses Object.assign to merge all the new state objects in the mappedStates array into a new object (the first parameter, {}). What are the three dots ... for? That's the spread operator. It takes every element in the mappedStates array and turns them into direct arguments of the Object.assign method.

This example makes it clear:

Object.assign({}, ...mappedStates)

is the same as

Object.assign({}, {AZ: "Arizona"}, {NY: "New York"})

That's it!

Upvotes: 10

djaszczurowski
djaszczurowski

Reputation: 4515

_.reduce(array, function(memo, current) { return _.assign(memo, current) },  {})

Upvotes: 23

iamricard
iamricard

Reputation: 493

I think an even shorter solution would be:

Object.assign({}, ...array)

I know you asked for lodash, but it doesn't seem like you even need this way. Unless you want to use _.extend.

Upvotes: 28

udnisap
udnisap

Reputation: 909

Use fromPairs on lodash 4. https://lodash.com/docs#fromPairs

_.fromPairs([['fred', 30], ['barney', 40]]);

Upvotes: 1

Adam Boduch
Adam Boduch

Reputation: 11211

Here's a shorter version:

_.transform(array, _.ary(_.extend, 2),  {});

The transform() function is like reduce(), except it's not expecting you to return anything. Since extend() is altering it's first argument, we can just pass it straight to transform(). It's wrapped in ary() to make sure it only gets 2 arguments passed to it.

Upvotes: 11

Related Questions