How to get a subset of a javascript object's properties excluding undefined or null properties

Viewed 454

I can have different version of an object:

myObject1 = { 
  color: 'red',
  size : 'big',
  name : 'Beautiful red',
  count: 2
};

myObject2 = { 
  color: 'blue',
  name : 'Awesome blue',
  count : null
};

I need a helper to keep only value i want and which exist :

function myHelper() {
   ?????
}


myHelper(myObject1, ['color','size','count']) // => { color: 'red', size : 'big', count:2}
myHelper(myObject2, ['color','size','count']) // => { color: 'blue'}

Anyone already created it ?

7 Answers

Convert the object to entries and filter by:

  • Object property (key) exists in the desired key list (props)
  • Value (val) is not null.

const myObject1 = { 
  color: 'red',
  size : 'big',
  name : 'Beautiful red',
  count: 2
};

const myObject2 = { 
  color: 'blue',
  name : 'Awesome blue',
  count : null
};

function myHelper(obj, props) {
  return Object.fromEntries(Object.entries(obj)
    .filter(([key, val]) => props.includes(key) && val != null));
}

console.log(myHelper(myObject1, ['color','size','count']));
console.log(myHelper(myObject2, ['color','size','count']));
.as-console-wrapper { top: 0; max-height: 100% !important; }

If you want to optimize this, you can change the "array includes" to a "set has" check via:

const myHelper = (obj, props) => (pSet => Object.fromEntries(Object.entries(obj)
    .filter(([key, val]) => pSet.has(key) && val != null)))
(new Set(props));

Check the browser compatibility before you use the Object.fromEntries here


You can do this using Object.entries to loop over the object entries ([key, value] pairs) and filter the object key k if it is in the supplied array (used a Set for faster lookup) and the value v which are not null.

Then pass those array of entries to the Object.fromEntries and get it as an object:

myObject1 = {
  color: 'red',
  size: 'big',
  name: 'Beautiful red',
  count: 2
};
myObject2 = {
  color: 'blue',
  name: 'Awesome blue',
  count: null
};
function myHelper(obj, arr) {
  return Object.fromEntries(
    Object.entries(obj)
    .filter(([k, v]) => new Set(arr).has(k) && v !== null)
  );
}
console.log(myHelper(myObject1, ['color', 'size', 'count']))
console.log(myHelper(myObject2, ['color', 'size', 'count']))

Another option would be to loop over the given keys in the arr and filter those which are present in the given obj and are not null.

Then map to an array of [key, value] pairs and supply that as an argument to the Object.fromEntries to output as an object:

myObject1 = {
  color: 'red',
  size: 'big',
  name: 'Beautiful red',
  count: 2
};
myObject2 = {
  color: 'blue',
  name: 'Awesome blue',
  count: null
};
function myHelper(obj, arr) {
  return Object.fromEntries(
   arr.filter(k => obj[k]).map(k => [k, obj[k]])
  );
}
console.log(myHelper(myObject1, ['color', 'size', 'count']))
console.log(myHelper(myObject2, ['color', 'size', 'count']))

It can be simply done using Array.reduce for keys.

myObject1 = { 
  color: 'red',
  size : 'big',
  name : 'Beautiful red',
  count: 2
};

myObject2 = { 
  color: 'blue',
  name : 'Awesome blue',
  count : null
};

function myHelper(input, keys) {
  const result = keys.reduce((acc, cur) => {
    if (input[cur]) {
      acc[cur] = input[cur];
    }
    return acc;
  }, {});
  return result;
}


console.log(myHelper(myObject1, ['color','size','count'])); // => { color: 'red', size : 'big', count:2}
console.log(myHelper(myObject2, ['color','size','count'])); // => { color: 'blue'}

Using Array.reduce we can achieve this

let myObject1 = { 
  color: 'red',
  size : 'big',
  name : 'Beautiful red',
  count: 2
};

let myObject2 = { 
  color: 'blue',
  name : 'Awesome blue',
  count : null
};

const myHelper = (data, keys) => keys.reduce((res, key) => {
  //check if the data is available in the provided object for the given key, if so add it to the result object.
  if (data[key]) {
    res[key] = data[key]
  };
  return res;
}, {})


console.log(myHelper(myObject1, ['color', 'size', 'count']))
console.log(myHelper(myObject2, ['color', 'size', 'count']))
.as-console-wrapper {
  max-height: 100% !important;
}

You could .map() over your key array and build a new object based on your key array. To build the new object from the array, you can map the keys to objects. You can then merge this array of objects into one object using Object.assign():

const myObject1 = { color: 'red', size : 'big', name : 'Beautiful red', count: 2 };
const myObject2 = { color: 'blue', name : 'Awesome blue', count : null };

function myHelper(obj, arr) {
  return Object.assign(
    {}, ...arr.map(k => obj[k] != undefined ? {[k]: obj[k]} : {})
  );
}

console.log(myHelper(myObject1, ['color','size','count'])); // => { color: 'red', size : 'big', count:2}
console.log(myHelper(myObject2, ['color','size','count'])); // => { color: 'blue'}

By building the object from the keys (rather than filtering out your input object), you save the need to check if the current entry is in your keys array.

Some of the answers posted here do not explicitly check for undefined and null thus if the property value is an empty string "" or 0 they will be filtered as well, which I'm guessing is not what you want.

You can use .getOwnPropertyNames and .reduce to filter the properties you want.

function keep(obj = {}, props = []) {
  return Object.getOwnPropertyNames(obj).reduce((acc, prop) => {
    if (obj[prop] !== undefined && obj[prop] !== null && props.includes(prop)) {
      return { ...acc, [prop]: obj[prop] };
    }

    return acc;
  }, {});
}

const cleanedObj = keep({ color: undefined, size: null, count: 0, age: 20 }, [
  "color",
  "size",
  "count",
  "age",
]);

console.log(cleanedObj); // { count: 0, age: 20 }

function myHelper (sourceObj, [...keys]) {
  let objSubset = Object.entries(sourceObj)
    .filter(([key]) => keys.includes(key))
    .filter(([, value]) => value !== undefined && value !== null)
    .reduce((newObj, [key, val]) => Object.assign(newObj, { [key]: val }), {});
  return objSubset
}

myObject1 = { 
  color: 'red',
  size : 'big',
  name : 'Beautiful red',
  count: 2
};

myObject2 = { 
  color: 'blue',
  name : 'Awesome blue',
  count : null
};

let x = myHelper(myObject1, ['color','size','count']);
let y = myHelper(myObject2, ['color','size','count']);

console.log(x)
console.log(y)

The function will not return object with values that are undefined and null but will still return object with 0, empty string "" and Boolean values.

Related