Shubham Kumar
Shubham Kumar

Reputation: 2465

How to filter out objects from array of object on the basics of object id

I am using react-native where i have to filter out the objects from object array on the basics of id which is provides in another array of object. i have array object as:

var objArr = [
    {name:'a',id:1},
    {name:'ab',id:2},
    {name:'abc',id:3}
];
var keys = [
    {user_id:1},
    {user_id:2}
];
var filterResult = objArr.filter((f) => {
                      !this.keys.includes(f)
                   });

how to remove objects from array where id is equal to user id of keys?

Upvotes: 1

Views: 145

Answers (2)

Val
Val

Reputation: 22797

For pure javascript, this works for your case with filter & reduce, (try run below code snippet)

var objArr = [
    {name:'a',id:1},
    {name:'ab',id:2},
    {name:'abc',id:3}
];
var keys = [
    {user_id:1},
    {user_id:2}
];

var filtered = objArr.filter( (o) => {
    return keys.reduce( (final, k) => {
        return final && !(k.user_id == o.id);
    }, true);
});

console.log(filtered);

To prevent reinventing the wheel, suggest to use existing library for this.

lodash does exactly what you need, with differenceWith.

So it becomes clean and elegant:

const filtered = _.differenceWith(objArr, keys, (a, b) => a.id == b.user_id);

Try run code snippet below.

var objArr = [
    {name:'a',id:1},
    {name:'ab',id:2},
    {name:'abc',id:3}
];
var keys = [
    {user_id:1},
    {user_id:2}
];

const filtered = _.differenceWith(objArr, keys, (a, b) => a.id == b.user_id);

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

Use lodash for react-native:

npm i lodash

and

import _ from 'lodash';

Update 2:

If you're doing performance critical code, that's a totally different story. you have to tune your code by making index, avoid all handy functions like filter, reduce, use traditional for-loop instead.

I made a quick one, it's about 50 times faster than lodash (300 ms to 6 ms), on 100k of objects with 3k of keys:

var filtered = [];
var indexes = {};
for (var i=0; i<keys.length; ++i) {
    indexes[keys[i].user_id] = true;
}
for (var i=0; i<objArr.length; ++i) {
    !indexes[objArr[i].id] && filtered.push(objArr[i]);
}

/* create objects */
function guid() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000)
      .toString(16)
      .substring(1);
  }
  return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
    s4() + '-' + s4() + s4() + s4();
}

function makeRand() {
  return Math.floor(Math.random() * 5000);
}

var objArr = [];
for (var i=0; i<100000; ++i) {
    objArr.push({
        name: guid(),
        id: makeRand()
    });
}

var keys = [];
for (var i=0; i<3000; ++i) {
    keys.push({
        user_id: makeRand()
    });
}

/* execute method 1 */
console.time('measure method 1');
var filtered = objArr.filter( (o) => {
    return keys.reduce( (final, k) => {
        return final && !(k.user_id == o.id);
    }, true);
});
console.timeEnd('measure method 1');
console.log('measure method 1 totally', filtered.length, ' objects');

/* execute method 2 */
console.time('measure method 2');
var filtered = _.differenceWith(objArr, keys, (a, b) => a.id == b.user_id);
console.timeEnd('measure method 2');
console.log('measure method 2 totally', filtered.length, ' objects');

/* execute method 3 */
console.time('measure method 3');
var filtered = [];
var indexes = {};
for (var i=0; i<keys.length; ++i) {
    indexes[keys[i].user_id] = true;
}
for (var i=0; i<objArr.length; ++i) {
    !indexes[objArr[i].id] && filtered.push(objArr[i]);
}
console.timeEnd('measure method 3');
console.log('measure method 3 totally', filtered.length, ' objects');
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

Upvotes: 1

Kit Masaracchia
Kit Masaracchia

Reputation: 101

One way you could do this is to reduce your keys objects to an array of numbers. The idea is to compare each element.id in your objArr to the ids in your keys array. This seems like what you're trying to do above.

1) Reduce keys:

var reducedKeys = keys.reduce((total, each) => {
   total.push(each.user_id);
   return total;
}, []);

2) Filter out ids not included in keys:

var filterResult = objArr.filter((each) => {
   if (!reducedKeys.includes(each.id)) {
       return each;
   }
});

If you:

console.log(filterResult)

the result is:

[ { name: 'abc', id: 3 } ]

Upvotes: 0

Related Questions