31

I'm about to use forOwn to iterate through an object's properties and create an array manually and can't helping thinking there's a oneliner already available to do it.

{ 
  prop1 : "value",
  prop2: { sub:1}
}

to:

[ 
   {key: "prop1", value: "value"},
   {key: "prop2", value: {sub:1}}
]

Thanks

6 Answers 6

40

You can use lodash's _.map() with shorthand property names:

const obj = { 
  prop1 : "value",
  prop2: { sub:1}
};

const result = _.map(obj, (value, prop) => ({ prop, value }));

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>

Or you can do it using Object#entries with Array.map() and array destructuring:

const obj = { 
  prop1 : "value",
  prop2: { sub:1}
};

const result = Object.entries(obj).map(([prop, value]) => ({ prop, value }));

console.log(result);

Sign up to request clarification or add additional context in comments.

5 Comments

I've marked this as the answer as it fits my problem using lodash as requested. However, I've added a _.map to jsperf page comparing them. jsperf.com/loop-for-in-vs-object-keys-foreach/19 (excuse the additional snippet someone has added for the array op - completely ruined the test), but when comparing the forOwn with map, there's no real benefit to it
The benefit is not in the performance, but in "oneliner already available to do it" as you requested :) Anyhow, remember that the difference in performance is only noticeable in a very large amount of items, and if that is not the issue go with _.map() as it's more readable (at least for me).
Object.entries is only available in ES2017, so if using ES2015 (ES6), it's not possible.
why is it: const result = _.map(obj, (value, prop) => ({ prop, value })); and not: const result = _.map(obj, (prop, value) => ({ prop, value })); ?
Because when lodash's map passes the key (prop) as the 2nd param.
13

You don't even need lodash for that:

var arr = Object.keys(obj).map(function(key){
  return { key: key, value: obj[key] };
});

2 Comments

thanks for answer, interestingly Object.keys is slower than forOwn. jsperf.com/loop-for-in-vs-object-keys-foreach/19 - someone's ruined the test by adding some array ops to it, but look at Object.keys vs _.forOwn vs the new one i've added _.map
@sambomartin Of course it will be "faster" since internally lodash just uses while loop for iteration. But then again, the question never asked for performance but for something that's already available.
10

A little bit of ES6 :

_.map( obj, (value, key) => ({key,value}) )

Comments

4

You can use pairs if it fits your case:

_.pairs({ 'barney': 36, 'fred': 40 });
// → [['barney', 36], ['fred', 40]]

Ref: https://lodash.com/docs#pairs

1 Comment

But it doesn't fit his case.
3

If you are using lodash/fp you can use _.entries

const a = { one: 123, two: { value: 'b' }};

const pairs = _.entries(a).map(p => ({ key:p[0], value: p[1] }))

console.log(pairs)
// [
//   {
//     "key": "one",
//     "value": 123
//   },
//   {
//     "key": "two",
//     "value": {
//       "value": "b"
//     }
//   }
// ]
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash-fp/4.15.0/lodash-fp.js"></script>

Comments

1

In response to Ori's comment and for completeness, I've posted the _.forOwn version. It's marginally faster but you need to declare the array first (not-a-one-liner).

var arr = [];
_.forOwn(obj,function(item, key) {
    arr.push({ property : key, value : item});
});

1 Comment

@ori this is the forOwn version. thanks for your help. (jsperf.com/loop-for-in-vs-object-keys-foreach/19)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.