Now I have two object arrays,
var arr1 = [{id: 0, name: 'Jack'}, {id: 1, name: 'Ben'}, {id: 2, name: 'Leon'}, {id: 3, name: 'Gavin'}];
var arr2 = [{id: 0, name: 'Jack'}, {id: 5, name: 'Jet'}, {id: 2, name: 'Leon'}];
I want to remove those objects of same id
in arr1
and arr2
, so the results are:
var arr1 = [{id: 1, name: 'Ben'}, {id: 3, name: 'Gavin'}];
var arr2 = [{id: 5, name: 'Jet'}];
How to implement it with lodash
or underscore
?
Here are my implementation.
arr1_ids = _.pluck(arr1, 'id');
arr2_ids = _.pluck(arr2, 'id');
same_ids = _.intersection(arr1_ids, arr2_ids);
arr1 = _.remove(arr1, function(e) { return !_.contains(same_ids, e.id); });
arr2 = _.remove(arr2, function(e) { return !_.contains(same_ids, e.id); });
Is there any better way to do that?
Now I have two object arrays,
var arr1 = [{id: 0, name: 'Jack'}, {id: 1, name: 'Ben'}, {id: 2, name: 'Leon'}, {id: 3, name: 'Gavin'}];
var arr2 = [{id: 0, name: 'Jack'}, {id: 5, name: 'Jet'}, {id: 2, name: 'Leon'}];
I want to remove those objects of same id
in arr1
and arr2
, so the results are:
var arr1 = [{id: 1, name: 'Ben'}, {id: 3, name: 'Gavin'}];
var arr2 = [{id: 5, name: 'Jet'}];
How to implement it with lodash
or underscore
?
Here are my implementation.
arr1_ids = _.pluck(arr1, 'id');
arr2_ids = _.pluck(arr2, 'id');
same_ids = _.intersection(arr1_ids, arr2_ids);
arr1 = _.remove(arr1, function(e) { return !_.contains(same_ids, e.id); });
arr2 = _.remove(arr2, function(e) { return !_.contains(same_ids, e.id); });
Is there any better way to do that?
Share Improve this question edited May 27, 2015 at 5:47 Ja͢ck 174k39 gold badges266 silver badges314 bronze badges asked May 27, 2015 at 4:13 zangwzangw 48.5k23 gold badges206 silver badges241 bronze badges 3-
Cant this be acplished with
.uniq
? – Dom Commented May 27, 2015 at 4:15 -
How to do that with
uniq
? – zangw Commented May 27, 2015 at 4:28 - Define "better". Is that faster? Less code? Easier to maintain? ;-) – RobG Commented May 29, 2015 at 21:56
3 Answers
Reset to default 11Can you use _.difference?
same_elements = _.intersection(arr1, arr2);
arr1 = _.difference(arr1, same_elements);
arr2 = _.difference(arr2, same_elements);
I'm not sure how this should be done with underscore or lodash, but here's a JavaScript implementation.
It creates a filter function that you can then apply to both arrays to only keep the elements that aren't part of the intersection.
var arr1 = [{id: 0, name: 'Jack'}, {id: 1, name: 'Ben'}, {id: 2, name: 'Leon'}, {id: 3, name: 'Gavin'}];
var arr2 = [{id: 0, name: 'Jack'}, {id: 5, name: 'Jet'}, {id: 2, name: 'Leon'}];
var negative_intersection_filter = function(a, b) {
// create a map to speed up the filtering later
var map = a.reduce(function(map, current) {
// perform the intersection
map[current.id] = b.some(function(item) {
return item.id == current.id;
});
return map;
}, {});
// our filtering function, simple
return function(item) {
return !map[item.id];
}
}(arr1, arr2);
// apply the filter here
arr1 = arr1.filter(negative_intersection_filter);
arr2 = arr2.filter(negative_intersection_filter);
console.log(arr1);
console.log(arr2);
I think your algorithm is about right, here's a slightly different approach in plain js. I've used a, b
instead of arr1, arr2
for brevity:
// Collect ids and sort
var ids = a.map(function(obj) {return obj.id}).concat(b.map(function(obj) {return obj.id})).sort();
// Get IDs that aren't duplicates
var nonDups = ids.filter(function(v, i, o){return v !== o[i-1] && v !== o[i+1]});
// Keep only the non-duplicates in each array
a.reduceRight(function(pre, cur, i, o){if (nonDups.indexOf(cur.id) == -1) o.splice(i, 1)},0);
b.reduceRight(function(pre, cur, i, o){if (nonDups.indexOf(cur.id) == -1) o.splice(i, 1)},0);
JSON.stringify(a) // [{"id":1,"name":"Ben"},{"id":3,"name":"Gavin"}]
JSON.stringify(b) // [{"id":5,"name":"Jet"}]
reduceRight is just used to iterate over each array backwards so that splicing doesn't affect the iteration.