1

I need a function that given a list of attributes, keep only the values that key exists in the list.

Examples:

attrs = ['a', 'b', 'c']
obj = {'a': 1, 'b': 2, 'c': 3}
return = {'a': 1, 'b': 2, 'c': 3}

attrs = ['a', 'b']
obj = {'a': 1, 'b': 2, 'c': 3}
return = {'a': 1, 'b': 2}

This is what I have so far, but it is not working as expected:

this.keepKnownAttributes = function(attrs, obj) {
        let ret = {};
        attrs.forEach((attr) => {
            if(obj.hasOwnProperty(attr)){
                Object.assign(ret, {attr: obj[attr]});
            }
        });
        return ret;
    };
Rogger Fernandes
  • 805
  • 4
  • 14
  • 28
  • 3
    Possible duplicate of [Object properties dynamic delete](https://stackoverflow.com/questions/13875338/object-properties-dynamic-delete) – Heretic Monkey Feb 18 '19 at 12:02
  • If a value that exists in `attrs` doesn't exist in `obj` should it be ignored or added as undefined? – nick zoum Feb 18 '19 at 12:08

8 Answers8

2

You can use .reduce to build a new object from your current array of keys:

const filterObj = (attr, obj) => 
  attr.reduce((acc, key) => (acc[key] = obj[key], acc), {})

console.log(filterObj(['a', 'b', 'c'], {'a': 1, 'b': 2, 'c': 3}));
console.log(filterObj(['a', 'b'], {'a': 1, 'b': 2, 'c': 3}));
Nick Parsons
  • 45,728
  • 6
  • 46
  • 64
  • Not sure why creating an new object and spreading the keys every time is necessary. You can just do `acc[key] = obj[key]; return acc;` – nick zoum Feb 18 '19 at 12:19
1

You can use Object.keys() and .reduce() methods:

const attrs1 = ['a', 'b', 'c']
const obj1 = {'a': 1, 'b': 2, 'c': 3}

const attrs2 = ['a', 'b']
const obj2 = {'a': 1, 'b': 2, 'c': 3}

const filterObj = (arr, obj) => Object.keys(obj)
                                      .filter(k => arr.includes(k))
                                      .reduce((r, c) => (r[c] = obj[c], r), {})
    
console.log(filterObj(attrs1, obj1));
console.log(filterObj(attrs2, obj2));
Mohammad Usman
  • 37,952
  • 20
  • 92
  • 95
1

Just use reduce and pass in an empty Object. In each iteration just copy the property from obj to the accumulator and then return it.

Below version adds all elements that exist in attrs

function test(attrs, obj) {
  return attrs.reduce(function(accumulator, currentValue) {
    accumulator[currentValue] = obj[currentValue];
    return accumulator;
  }, {});
}

console.log(test(['a', 'b', 'c'], { 'a': 1, 'b': 2, 'c': 3 }));
console.log(test(['a', 'b'], { 'a': 1, 'b': 2, 'c': 3 }));
console.log(test(['a', 'b', 'c'], { 'a': 1, 'b': 2 }));

Below version only adds elements that exist in both attrs and obj

function test(attrs, obj) {
  return attrs.reduce(function(accumulator, currentValue) {
    if(obj.hasOwnProperty(currentValue))
       accumulator[currentValue] = obj[currentValue];
    return accumulator;
  }, {});
}

console.log(test(['a', 'b', 'c'], { 'a': 1, 'b': 2, 'c': 3 }));
console.log(test(['a', 'b'], { 'a': 1, 'b': 2, 'c': 3 }));
console.log(test(['a', 'b', 'c'], { 'a': 1, 'b': 2 }));

Here is the short arrow version

function test(attrs, obj) {
  return attrs.reduce((a, c) => { a[c] = obj[c]; return a; }, {});
}

console.log(test(['a', 'b', 'c'], { 'a': 1, 'b': 2, 'c': 3 }));
console.log(test(['a', 'b'], { 'a': 1, 'b': 2, 'c': 3 }));
console.log(test(['a', 'b', 'c'], { 'a': 1, 'b': 2 }));

And tada. No need to use Object.keys or Array.prototype.filter if you just reduce the array instead of the properties of the object.

nick zoum
  • 7,216
  • 7
  • 36
  • 80
0

Use .hasOwnProperty() method. It returns true if the object is having that property. Refer

var attrs = ['a', 'b']
var obj = {
  'a': 1,
  'b': 2,
  'c': 3
}
var obj1 = {};
attrs.forEach(e =>obj.hasOwnProperty(e)?obj1[e] = obj[e]:false)
console.log(obj1)
ellipsis
  • 12,049
  • 2
  • 17
  • 33
0

You could iterate through all the keys of the object and store them into an array with keys to be deleted. Later, you can simply delete the properties of the object with delete. You can get a list with all the keys using Object.keys(obj).

attrs1 = ['a', 'b', 'c']
obj1 = {
  'a': 1,
  'b': 2,
  'c': 3
}

attrs2 = ['a', 'b']
obj2 = {
  'a': 1,
  'b': 2,
  'c': 3
}

keepKnownAttributes = function(attrs, obj) {
  let keysToDelete = [];
  Object.keys(obj).forEach(key => {
    if (!attrs.includes(key)) {
      keysToDelete.push(key);
    }
  });

  keysToDelete.forEach(key => {
    delete obj[key];
  });

  return obj;
};

console.log(keepKnownAttributes(attrs1, obj1));
console.log(keepKnownAttributes(attrs2, obj2));

The example can be minified using some lambda functions

attrs1 = ['a', 'b', 'c']
obj1 = {
  'a': 1,
  'b': 2,
  'c': 3
}

attrs2 = ['a', 'b']
obj2 = {
  'a': 1,
  'b': 2,
  'c': 3
}

keepKnownAttributes = function(attrs, obj) {
  Object.keys(obj).filter(e => !attrs.includes(e)).map(key => delete obj[key]);
  return obj;
};

console.log(keepKnownAttributes(attrs1, obj1));
console.log(keepKnownAttributes(attrs2, obj2));

You don't actually have to return anything, since you modify the original object. Cheers!

Adrian Pop
  • 1,879
  • 5
  • 28
  • 40
0

You can do that using Array.prototype.filter() and Array.prototype.reduce(). First filter out the keys which which are present in attrs and then return new object containing filtered keys and its values.

let obj = {'a': 1, 'b': 2, 'c': 3}

function remove(obj,attrs){
  return Object.keys(obj).filter(a => attrs.includes(a)).reduce((ac,a) => {
    ac[a] = obj[a];
    return ac;
  },{})
}
console.log(remove(obj,['a','b','c']));
console.log(remove(obj,['a','b']));
Maheer Ali
  • 35,834
  • 5
  • 42
  • 73
0

You can use reduce:

const attrs = ['a', 'b']
const obj = {'a': 1, 'b': 2, 'c': 3}

const obj2 = attrs.reduce((acc, key) => 
  (acc[key] = obj[key], acc)
, {});

As generic function, would looks like:

const filterAttrsFrom = (target, attrs) =>
  attrs.reduce((acc, key) => 
    (acc[key] = target[key], acc)
  , {});
ZER0
  • 24,846
  • 5
  • 51
  • 54
0

this too works ;-)

function someName(attrs, obj) {
  let newObj = {};
  for (var object in obj) {
    if (attrs.includes(object)) {
      newObj[object] = obj[object];
    }
  }
  return newObj
}

console.log(someName(["a", "b"], { a: 1, b: 2, c: 3 }));