Reputation: 1031
I want to remove an object in array if not present in another array. I tried to search and found similar question in this link but have a different array source.
Here is the example from link above :
var check = [1, 2, 3];
var allowed = [1];
var filtered = check.filter(function(item) {
return allowed.indexOf(item) > -1;
});
console.log(filtered);
Example above remove number in array check
if not present in array allowed
. In my case the source array contain an object like example below :
var check = [
{
name: 'Peter',
location: 'florida'
},
{
name: 'Robert',
location: 'California'
}
];
var allowed = [
{
name: 'Robert',
location: 'Boston'
}
];
var filtered = check.filter(function(item) {
return allowed.indexOf(item.name) > -1;
});
console.log(filtered);
I tried to run the code and the result is an empty array.
Result i expect :
[
{
name: 'Robert',
location: 'California'
}
]
Anyone can please help me to make the result as i expect?
Upvotes: 1
Views: 3469
Reputation: 11
There are multiple approaches depending on what you need.
For a dirty check where the objects will have the same memory reference on both arrays you can do the following.
var firstPerson = {
name: 'Peter',
location: 'florida'
}
var secondPerson = {
name: 'Robert',
location: 'California'
}
var allowed = [secondPerson];
var check = [firstPerson, secondPerson];
var result = check.filter(item => allowed.includes(item));
console.log(result);
For an specific attribute check you can use find
and compare the check
and allowed
, by an attribute like name
or location
var check = [
{
name: 'Peter',
location: 'florida'
},
{
name: 'Robert',
location: 'California'
}
];
var allowed = [
{
name: 'Robert',
location: 'Boston'
}
];
var result = check.filter(checkPerson => allowed.find(allowPerson => allowPerson.name === checkPerson.name));
console.log(result);
For a nested object check you would require to check the items recursively, I use this utility I created some time ago called deepCompare
, is an alternative to Lodash's isEqual
that only weights 880B
var check = [
{
name: 'Peter',
location: {
street: "fridtjof nansens vei 8511",
city: "ågotnes",
state: "buskerud",
postcode: "8766",
coordinates: {
latitude: "50.4828",
longitude: "-84.6920"
}
}
},
{
name: 'Robert',
location: {
street: "schillerstraße 69",
city: "velburg",
state: "saarland",
postcode: 72100,
coordinates: {
latitude: "30.4655",
longitude: "9.1938"
}
}
}
];
var allowed = [
{
name: 'Robert',
location: {
street: "schillerstraße 69",
city: "velburg",
state: "saarland",
postcode: 72100,
coordinates: {
latitude: "30.4655",
longitude: "9.1938"
}
}
}
];
var result = check.filter(checkPerson => allowed.some(allowPerson => deepCompare(checkPerson, allowPerson)));
console.log(result);
<script>
/**
* Deep Compare
* @param { * } value first entry value
* @param { * } other second entry value
* @param { Boolean } sorted Sort any array before deep comparison
*/
const deepCompare = (value, other, sorted) => {
/**
* Compare possible primitives
* Object.is works like `===` but additionally differes positive from negative values
* I.E:
* Object.is(-0, 0) // False
* -0 === 0 // True
*/
if (Object.is(value, other)) return true;
/**
* Check if either value is undefined or the constructor is different for each value
* given the case return false
*/
if (!value || !other || value.constructor !== other.constructor) return false;
/**
* Check Object and Array deep comparisons
*/
switch (value.constructor) {
case Array:
/**
* Check if both values have the same amount of items
* if they don't immediatelly omit the comparison and return false
*/
if (value.length === other.length) { return deepArrayCompare(value, other, sorted); }
return false;
case Object:
/**
* Check if both values have the same amount of keys
* if they don't immediatelly omit the comparison and return false
*/
if (Object.keys(value).length === Object.keys(other).length) { return deepObjectCompare(value, other, sorted); }
return false;
}
return false;
};
/**
* Deep Object Compare
* @param { * } value first entry value
* @param { * } other second entry value
*
* 'deepArrayCompare(Object.keys(value), Object.keys(other), sorted)'
* This checks that both objects have the same keys
* I.E:
* deepArrayCompare(Object.keys({ a: 1, b: 2, c:3 }), Object.keys({ a: 10, b: 22, c: 54 }), true) // True
* deepArrayCompare(Object.keys({ a: 1, b: 2, c:3 }), Object.keys({ g: 1, f: 2, d: 3 }), true) // False
*
* 'Object.keys(value).every(key => deepCompare(value[key], other[key]))'
* This iterates on each key of the object over a 'every' comparison and performs a deepCompare on both values
*
*/
const deepObjectCompare = (value, other) => deepArrayCompare(Object.keys(value), Object.keys(other), true) && Object.keys(value).every(key => deepCompare(value[key], other[key]));
/**
* Deep Array Compare
* @param { * } value first entry value
* @param { * } other second entry value
* @param { Boolean } sorted Sort any array before deep comparison
*
* '(sorted && value.sort(), sorted && other.sort(), ...)'
* This manages the optional sorting through Comma Operator
*
* 'value.every((item, index) => deepCompare(item, other[index]))'
* This performs the deepComparison of values between both arrays
*/
const deepArrayCompare = (value, other, sorted) => (sorted && value.sort(), sorted && other.sort(), value.every((item, index) => deepCompare(item, other[index])));
</script>
Upvotes: 1
Reputation: 74
The following intersect function would intersect any key on any given array of objects:
var check = [
{ name:'Peter', location:'florida' },
{ name:'Robert', location:'California'}
];
var allowed = [
{ name:'Robert', location:'Boston' }
];
function intersect(check, allowed) {
var allowed_map = allowed.reduce(function(map, obj) {
Object.keys(obj).forEach(function(key) {
if (!map[key]) {
map[key] = [];
}
map[key].push(obj[key]);
});
return map;
}, {});
return check.filter(function(item) {
return Object.keys(item).find(function(key) {
return allowed_map[key].indexOf(item[key]) != -1;
})
});
}
var filtered = intersect(check, allowed);
var allowed2 = [{ name:'Bob', location:'California' }];
var filtered2 = intersect(check, allowed2);
console.log('filtered',filtered);
console.log('filtered2',filtered2);
Upvotes: 1
Reputation: 171669
You can use Array#find()
var check = [{
name: 'Peter',
location: 'florida'
},
{
name: 'Robert',
location: 'California'
}
];
var allowed = [{
name: 'Robert',
location: 'Boston'
}];
var res = check.filter(function(cItem) {
return allowed.find(function(aItem) {
return cItem.name === aItem.name
})
})
console.log(res)
Upvotes: 4
Reputation: 1275
You need to check against the item names in the allowed
array.
Right now you're checking against the items in the allowed array, which type is an object.
Here's the problem: return allowed.indexOf(item.name) > -1;
Maybe this approach helps:
var check = [
{
name: 'Peter',
location: 'florida'
},
{
name: 'Robert',
location: 'California'
}
];
var allowed = [
{
name: 'Robert',
location: 'Boston'
}
];
function containsName(name, array){
return array.find(item => item.name === name);
}
var filtered = check.filter(function(item) {
return containsName(item.name, allowed)
});
console.log(filtered);
Upvotes: 2
Reputation: 18898
You can map allowed
to just contain the criteria that you are looking for (name):
var allowed = [{
name: 'Robert',
location: 'Boston'
}]
.map(obj => obj.name);
That will create an array of just names which is easier to test the indexOf
Example:
var check = [{
name: 'Peter',
location: 'florida'
},
{
name: 'Robert',
location: 'California'
}
];
var allowed = [{
name: 'Robert',
location: 'Boston'
}]
.map(obj => obj.name);
var filtered = check.filter(function(item) {
return allowed.indexOf(item.name) > -1;
});
console.log(filtered);
Upvotes: 3