How to get a subset of a javascript object’s properties

How to get a subset of a javascript object’s properties

Say I have an object:
elmo = {
color: ‘red’,
annoying: true,
height: ‘unknown’,
meta: { one: ‘1’, two: ‘2’}
};

I want to make a new object with a subset of its properties.
// pseudo code
subset = elmo.slice(‘color’, ‘height’)

//=> { color: ‘red’, height: ‘unknown’ }

How may I achieve this?

Solutions/Answers:

Solution 1:

Using Object Destructuring and Property Shorthand

const object = { a: 5, b: 6, c: 7  };
const picked = (({ a, c }) => ({ a, c }))(object);

console.log(picked); // { a: 5, c: 7 }

From Philipp Kewisch:

This is really just an anonymous function being called instantly. All of this can be found on the Destructuring Assignment page on MDN. Here is an expanded form

let unwrap = ({a, c}) => ({a, c});

let unwrap2 = function({a, c}) { return { a, c }; };

let picked = unwrap({ a: 5, b: 6, c: 7 });

let picked2 = unwrap2({a: 5, b: 6, c: 7})

console.log(picked)
console.log(picked2)

Solution 2:

I suggest taking a look at Lodash; it has a lot of great utility functions.

For example pick() would be exactly what you seek:

var subset = _.pick(elmo, ['color', 'height']);

fiddle

Solution 3:

If you are using ES6 there is a very concise way to do this using destructing. Destructing allows you to easily add on to objects using a spread, but it also allows you to make subset objects in the same way.

const object = {
  a: 'a',
  b: 'b',
  c: 'c',
  d: 'd',
}

// Remove "c" and "d" fields from original object:
const {c, d, ...partialObject} = object;
const subset = {c, d};

console.log(partialObject) // => { a: 'a', b: 'b'}
console.log(subset) // => { c: 'c', d: 'd'};

Solution 4:

While it’s a bit more verbose, you can accomplish what everyone else was recommending underscore/lodash for 2 years ago, by using Array.prototype.reduce.

var subset = ['color', 'height'].reduce(function(o, k) { o[k] = elmo[k]; return o; }, {});

This approach solves it from the other side: rather than take an object and pass property names to it to extract, take an array of property names and reduce them into a new object.

While it’s more verbose in the simplest case, a callback here is pretty handy, since you can easily meet some common requirements, e.g. change the ‘color’ property to ‘colour’ on the new object, flatten arrays, etc. — any of the things you need to do when receiving an object from one service/library and building a new object needed somewhere else. While underscore/lodash are excellent, well-implemented libs, this is my preferred approach for less vendor-reliance, and a simpler, more consistent approach when my subset-building logic gets more complex.

edit: es7 version of the same:

const subset = ['color', 'height'].reduce((a, e) => (a[e] = elmo[e], a), {});

edit: A nice example for currying, too! Have a ‘pick’ function return another function.

const pick = (...props) => o => props.reduce((a, e) => ({ ...a, [e]: o[e] }), {});

The above is pretty close to the other method, except it lets you build a ‘picker’ on the fly. e.g.

pick('color', 'height')(elmo);

What’s especially neat about this approach, is you can easily pass in the chosen ‘picks’ into anything that takes a function, e.g. Array#map:

[elmo, grover, bigBird].map(pick('color', 'height'));
// [
//   { color: 'red', height: 'short' },
//   { color: 'blue', height: 'medium' },
//   { color: 'yellow', height: 'tall' },
// ]

Solution 5:

There is nothing like that built-in to the core library, but you can use object destructuring to do it…

const {color, height} = sourceObject;
const newObject = {color, height};

You could also write a utility function do it…

const cloneAndPluck = function(sourceObject, keys) {
    const newObject = {};
    keys.forEach((obj, key) => { newObject[key] = sourceObject[key]; });
    return newObject;
};

const subset = cloneAndPluck(elmo, ["color", "height"]);

Libraries such as Lodash also have _.pick().

Solution 6:

I am adding this answer because none of the answer used Comma operator.

It’s very easy with destructuring assignment and , operator

const object = { a: 5, b: 6, c: 7  };
const picked = ({a,c} = object, {a,c})

console.log(picked); // { a: 5, c: 7 }