Check element presence in array in another array - javascript

I have following :
const arr1 = [{id: 1},{id: 2}]
const arr2 = [{id: 1},{id: 4},{id: 3}]
I want to check if elements in arr2 exists in arr1 or vice versa. I want to check for each element in array.
Desired output :
true
false
false
Usually it shouls give error , because one arrays length is longer than first , for the rest I want to get false

O(N) solution with set
const arr1 = [{id: 1},{id: 2}]
const arr2 = [{id: 1},{id: 4},{id: 3}]
const set = new Set()
arr1.forEach((a) => set.add(a.id))
arr2.forEach((b) => {
if (set.has(b.id)) {
console.log("arr1 and arr2 both share"+ b.id)
}
})

You can use array#map with array#some to check if object id in arr2 exist in arr1.
const arr1 = [{id: 1},{id: 2}],
arr2 = [{id: 1},{id: 4},{id: 3}],
result = arr2.map(({id}) => arr1.some(o => id === o.id));
console.log(result);

const arr1 = [{
id: 1
}, {
id: 2
}]
const arr2 = [{
id: 1
}, {
id: 4
}, {
id: 3
}]
let arr1id = arr1.map(i => i.id);
let result = arr2.map(a => arr1id.includes(a.id));
console.log(result);

use hashmap & use below 2 methods of map in java
boolean containsKey(Object key)
V get(Object key)
V get(Object key) to get the object that contains the value associated with the key from map1.
boolean containsKey(Object key) This method returns true if some key equal to the key exists within the map, else return false [ check it in map2]

Related

Remove array objects contained in another array by value

I have to remove all the objects from array that contain the same id present in another array.
This code works
myArray = [{id: 1, value: 'a'}, {id: 2, value: 'b'}, {id: 3, value: 'c'}];
itemsToRemove = [{id: 2, value: 'x'}, {id: 3, value: 'y'}];
for (const item of itemsToRemove) {
myArray.splice(myArray.findIndex(a => a.id === item.id), 1);
}
but I'm looking for a more elegant way to do it. I've tried also
const newArray = myArray.filter(a => itemsToRemove.findIndex(i => i.id === a.id));
but doesn't works. (it creates a new array, but at least one item with the same id remains in the new array).
Is there a clean and concise way to do it?
You're close, but as James said in the comments, findIndex is the wrong choice because it returns -1 when the item is not found. filter requires its predicate to return a boolean and -1 is not a boolean, so it's coerced to one. Unfortunately, -1 is truthy which doesn't match your intention in the predicate.
You can add a comparison to check that findIndex returned a value less than zero, or you can use find or some:
const myArray = [{id: 1, value: 'a'}, {id: 2, value: 'b'}, {id: 3, value: 'c'}];
const itemsToRemove = [{id: 2, value: 'x'}, {id: 3, value: 'y'}];
const newArray1 = myArray.filter(a => itemsToRemove.findIndex(i => i.id === a.id) < 0);
console.log(newArray1);
const newArray2 = myArray.filter(a => !itemsToRemove.find(i => i.id === a.id));
console.log(newArray2);
const newArray3 = myArray.filter(a => !itemsToRemove.some(i => i.id === a.id));
console.log(newArray3);
It's worth noting that find isn't supported in IE, nor is findIndex. some is supported by all browsers, so it's the most compatible.
some is also the most performant:
Test
Result
Operations/second
findIndex
10.63% slower
26632285
find
12.39% slower
26107649
some
fastest
29799972

Filtering an array of objects from an array

I have an array of objects lookups and an array filters. Now I want to filter the array from an array of objects using the object attribute name.
I used filter and some but I could not get the expected result.
EXPECTED RESULT:
[{id: 3, name: "Linkedin"}]
let lookups = [
{id: 1, name: "Twitter"},
{id: 2, name: "Facebook"},
{id: 3, name: "Linkedin"}
]
let filters = ["Facebook", "Twitter"]
const filtered = lookups.filter(lookup => filters.some(filter => filter.toLowerCase() != lookup.name.toLowerCase()));
console.log(filtered)
Your code gives those elements in result for which some of the values in filters is not equal to element's name. So for each element some of the name is not equal.
In other words you are using != with || which will always return true.
let a = "anything";
console.log(a !== "thing1" || a !== "thing2")
You need to use every() instead of some().
let lookups = [
{id: 1, name: "Twitter"},
{id: 2, name: "Facebook"},
{id: 3, name: "Linkedin"}
]
let filters = ["Facebook", "Twitter"]
const filtered = lookups.filter(lookup => filters.every(filter => filter.toLowerCase() !== lookup.name.toLowerCase()));
console.log(filtered)

Return a subset of an array of objects that matches a property of an another array of objects

inputs:
const parentArray = [
{id:1, name:'foo'},
{id:2, name:'bar'},
{id:4, name:'foobar'},
{id:6, name:'barfoo'}
]
const childArray = [
{parent_id:1, prop:'prop1'},
{parent_id:2, prop:'prop2'},
{parent_id:3, prop:'prop3'},
{parent_id:4, prop:'prop4'},
{parent_id:5, prop:'prop5'}
];
output:
const resultingArray = [
{id:1, name:'foo'},
{id:2, name:'bar'},
{id:4, name:'foobar'}
]
I want to compare the properties id and parent_id from both arrays and return a subset of parentArray for the matching properties
I've tried to filter them out but not having success, using lodash
You could take a Set for the wanted parents and filter the parent array.
var parents = [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }],
children = [{ parent_id: 1, prop: 'prop1' }, { parent_id: 3, prop: 'prop3' }],
wanted = new Set(children.map(({ parent_id }) => parent_id)),
result = parents.filter(({ id }) => wanted.has(id));
console.log(result);
You can do so with a combination of Array.filter() and Array.some() in the following way.
const resultingArray = parentArray
.filter(x => childArray.some( y => y.parent_id===x.id));
Check this JS bin
We can use a Set as a lookup table for the parent_id data from the child and then use Array.prototype.filter to filter through the parent entries and use Set#has to check if the id is contained in the Set:
const parentArray = [{id:1, name:'foo'},{id:2, name:'bar'}, {id:4, name:'foo'},{id:6, name:'bar'}]
const childArray = [
{parent_id:1, prop:'prop1'},
{parent_id:2, prop:'prop2'},
{parent_id:3, prop:'prop3'},
{parent_id:4, prop:'prop4'},
{parent_id:5, prop:'prop5'}
];
function findSubSet(){
const lookup = new Set(childArray.map(({parent_id}) => parent_id));
return parentArray.filter(p => lookup.has(p.id));
}
console.log(findSubSet(parentArray, childArray));
You can use reduce & findIndex. In the reduce callback use findIndex to check if there exist same id.If id exist it will return the index & if not then it will return -1. So if index is not -1 then you can push the value to accumulator(acc)
const parentArray = [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
const childArray = [{
parent_id: 1,
prop: 'prop1'
},
{
parent_id: 2,
prop: 'prop2'
},
{
parent_id: 3,
prop: 'prop3'
}
]
let filteredData = parentArray.reduce(function(acc, curr) {
let getIndexFromChild = childArray.findIndex(function(item) {
return curr.id === item.parent_id
});
if (getIndexFromChild !== -1) {
acc.push(curr)
}
return acc;
}, []);
console.log(filteredData)
As previously mentioned, your example is unclear, but filtering an array using another array, assuming you want to use the properties id from parentArray and parent_id from childArray, then I would use this:
resultingArray = childArray.filter(c=> parentArray.find(p => p.id === c.parentId);
You can use a mixture of filter and some to get the matching values:
const parentArray = [{id:1, name:'foo'},{id:2, name:'bar'}]
const childArray = [
{parent_id:1, prop:'prop1'},
{parent_id:3, prop:'prop3'}
]
let result = parentArray.filter(i => childArray.some(j => j.parent_id == i.id))
console.log(result)

Filter an array by values which aren't a property value in an array of objects - Javascript

I have an array of values, for example:
let values = [1, 2, 3, 4, 5];
And I have another array, containing objects, for example:
let objects = [{name: 'Dennis', value: 2}, {name: 'Charlie', value: 4}];
I would like to produce an array that only contains values that aren't present in the value property of my objects.
So from the examples above, I would return an array of [1, 3, 5]
What I've got at the moment is:
let missingValues = [];
for (let i = 0; i < values.length; i++) {
if (!objects.filter(obj => obj.value === values[i]) {
missingValues.push(values[i]);
}
}
This works, but feels slightly messy, is there a more efficient way to do this?
You could filter the values with a look up in the objects array.
var values = [1, 2, 3, 4, 5],
objects = [{ name: 'Dennis', value: 2 }, { name: 'Charlie', value: 4 }],
result = values.filter(v => !objects.find(({ value }) => value === v));
console.log(result);
...is there a more efficient way to do this?
I assume you really mean "efficient" (as opposed to "concise").
Yes, you can build an object or Set containing the values from the second array, and then use that to filter instead:
let values = [1, 2, 3, 4, 5];
let objects = [{name: 'Dennis', value: 2}, {name: 'Charlie', value: 4}];
let valueSet = new Set();
for (const obj of objects) {
valueSet.add(obj.value);
}
let missingValues = values.filter(value => !valueSet.has(value));
console.log(missingValues);
(You can also use an object for the same thing, if you prefer. let valueSet = Object.create(null); then valueSet[value] = true and !valueSet[value].)
This is only worth doing if the product of the arrays is quite large (hundreds of thousands of entries) or you're doing this a lot.

Filter an array of objects and extract its property by using an array of keys

im having this problem which i cant wrap around my head,
much better if put in a code.
//Array of objects sample
var objects = [{id:1, name:'test1'}, {id:2, name:'test2'}, {id:3, name: 'test3'}, {id:4, name:'test4'}];
var arrayOfKeys = [3,1,4];
//extract object name property if its id property is equivalent to one of arrayOfKeys [3,1]
//var arrayOfKeys = [3,1,4];
//output sample: extractedName=['test3','test1','test4'];
i've been using filter and map but no avail, also tried nesting filter inside map im getting an arrays of array and inside is a single object.
You could map the objects and ren map the wanted keys for getting the name.
var objects = [{ id: 1, name: 'test1' }, { id: 2, name: 'test2' }, { id: 3, name: 'test3' }],
arrayOfKeys = [3, 1],
result = arrayOfKeys.map((map => id => map.get(id).name)(new Map(objects.map(o => [o.id, o]))));
console.log(result);
I assume you need to map array numbers to id properties? Here's the code where you map through numbers and find inside your array to handle situations when there's no such id in objects array:
var objects = [{id:1, name:'test1'}, {id:2, name:'test2'}, {id:3, name: 'test3'}];
var arrayOfKeys = [3,1];
var res = arrayOfKeys.map(key => {
var found = objects.find(o => o.id == key);
return found ? found.name : false;
})
console.log(res)
let objects = [{id:1, name:'test1'}, {id:2, name:'test2'}, {id:3, name: 'test3'}, {id:4, name:'test4'}],
arrayOfKeys = [3,1,4];
let result = objects.reduce((res, obj) => { // loop over the array of objects
let index = arrayOfKeys.indexOf(obj.id); // check if the current object's id is in the array of keys
if(index !== -1) { // if it's there
res.push(obj.name); // then add the current object's name to the result array
arrayOfKeys.splice(index, 1); // remove its id from the array of keys so we won't search for it again (optional, slightly better than leaving it there)
}
return res;
}, []);
console.log(result);
I think you were on the right track with the filter. You can make it readable and concise with some.
var objects = [{id: 1,name: 'test1'}, {id: 2,name: 'test2'}, {id: 3,name: 'test3'}, {id: 4,name: 'test4'}],
arrayOfKeys = [3, 1, 4];
var result = objects.filter((x, i) => {
if (arrayOfKeys.some(k => x.id === k)) {
return true;
}
})
console.log(result.map(x=>x.name));
Something even shorter! would be
var objects = [{id: 1,name: 'test1'}, {id: 2,name: 'test2'}, {id: 3,name: 'test3'}, {id: 4,name: 'test4'}],arrayOfKeys = [3, 1, 4];
var result = objects.filter((x, i) => arrayOfKeys.some(k => x.id === k));
console.log(result.map(x=>x.name));

Categories