Compare an array of objects and an array of singular values - javascript

I have two arrays. One is filled with objects, the other is filled with values. See code below:
const data = [
{id: 1, name: 'ben'},
{id: 2, name: 'ben'},
{id: 3, name: 'ben'},
{id: 4, name: 'ben'}
];
const ids = [1,3,4,5]
I want to select only objects from the data array where the id property matches any of the value in the ids array.
How best should I go about this?
Thanks in advance

Here is a code snippet that might help.
const data = [{id:1, name:'ben'},{id:2, name:'ben'}, {id:3, name:'ben'}, {id:4, name:'ben'}];
const ids = [1,3,4,5];
const newData = data.filter(chunk => ids.includes(chunk.id));
console.log("Filtered Data", newData);

Easiest approach to do this is array filter function:
const data = [{id:1, name:'ben'},{id:2, name:'ben'}, {id:3, name:'ben'}, {id:4, name:'ben'}];
const ids = [1, 3, 4, 5];
const result = data.filter(({id}) => ids.includes(id));
console.log(result);

As an alternative way, you can use some method placed inside filter method:
data.filter(chunk => ids.some(s => s == chunk.id));
An example:
const data = [{id:1, name:'ben'},{id:2, name:'ben'}, {id:3, name:'ben'}, {id:4, name:'ben'}];
const ids = [1,3,4,5];
const newData = data.filter(chunk => ids.some(s => s== chunk.id));
console.log("Filtered Data", newData);

You can use Array.prototype.filter to filter the initial array and Array.prototype.includes to exclude unmatching entities:
const data = [
{ id: 1, name: "ben" },
{ id: 2, name: "ben" },
{ id: 3, name: "ben" },
{ id: 4, name: "ben" }
];
const ids = [1, 3, 4, 5];
const filteredData = data.filter(dataItem => ids.includes(dataItem.id));
console.log(filteredData); // [{"id":1,"name":"ben"},{"id":3,"name":"ben"},{"id":4,"name":"ben"}]

Related

How to correctly check relations inside arrays of objects?

I have two array of objects. In one I have data on items and its characteristics, and in the other I have
list of categories with the id key.
Both are fetching from an external API so I can't modify them manually.
first array of object:
[{
title: "xxx",
desc: "zzz",
genre_ids: [1, 2, 3]}
second array of object:
[{id: 1,
name: "women"}]
I want to display name's of the gander using second array.
I had two failed attempts:
first approach
{listCategory.map(z => {z.id.includes(item.genre_ids)
return (z.name)} ) }
second approach
{listCategory.filter(cat =>
cat.id === item.genre_ids
).map(categ => {
console.log("categ", categ.name)
return(<p key={uuid()}>{categ}</p>)})}
You can create another array that would be a Map of the first array where you are retrieving the second array data using a find
const firstArr = [{
title: "xxx",
desc: "zzz",
genre_ids: [1, 2, 3]
}]
const secondArr = [
{id: 1,name: "women"},
{id: 2,name: "men"},
{id: 3,name: "other"},
]
const arrWithAllInformations = firstArr.map(item => {
const { title, desc, genre_ids} = item
const genres_full = genre_ids.map(id => secondArr.find(genre => genre.id === id))
return {
title,
desc,
genres: genres_full
}
})
console.log(arrWithAllInformations)
You can then loop through the arrWithAllInformations objects and display the informations as you want.
More consise way :
const firstArr = [
{title: "xxx",desc: "zzz",genre_ids: [1, 2, 3]}
]
const secondArr = [
{id: 1,name: "women"},
{id: 2,name: "men"},
{id: 3,name: "other"},
]
const arrWithAllInformations = firstArr.map(item => ({...item, genres: item.genre_ids.map(id => secondArr.find(genre => genre.id === id))}))
console.log(arrWithAllInformations)
You can use flatMap and a Set to remove duplicates.
const first = [{
title: "xxx",
desc: "zzz",
genre_ids: [1, 2, 3]
}, {
title: "xxx",
desc: "zzz",
genre_ids: [1, 2, 4]
}];
const second = [{
id: 1,
name: "women"
}, {
id: 2,
name: "man"
}, {
id: 7,
name: "non-binary"
}];
const ids = new Set(first.flatMap(({
genre_ids
}) => genre_ids));
const filtered = second.flatMap(({
id,
name
}) => ids.has(id) ? name : []);
console.log(filtered);
You can simply achieve it by just using Array.forEach() method.
Live Demo :
const firstArr = [{
title: "xxx",
desc: "zzz",
genre_ids: [1, 2, 3]
}];
const secondArr = [{
id: 1,
name: "women"
}];
firstArr.forEach(({ genre_ids }) => secondArr.forEach(obj => {
if (genre_ids.includes(obj.id)) {
console.log(obj.name);
}
}));

Compare two array of objects and remove objects from first array if a property value is matched

I have 2 array of objects like
const arrayOne = [{id: 1, name: 'one'}, {id: 2, name: 'two'}, {id: 3, name: 'three'}];
const arrayTwo = [{id: 2, name: 'two'}, {id: 3, name: 'three'}];
Here, I need to compare both these arrays and remove matching objects from arrayOne, which should finally give
this.arrayOne = [{id: 1, name: 'one'}];
I tried like below but it is removing all objects from the array
this.arrayOne = this.arrayOne.filter(o1 => this.arrayTwo.some(o2 => o1.id === o2.id));
What I am doing wrong here? Please suggest. Thanks
const arrayOne = [
{ id: 1, name: "one" },
{ id: 2, name: "two" },
{ id: 3, name: "three" },
];
const arrayTwo = [
{ id: 2, name: "two" },
{ id: 3, name: "three" },
];
const arrayTwoIds = new Set(arrayTwo.map((el) => el.id));
const arrayOneFiltered = arrayOne.filter((el) => !arrayTwoIds.has(el.id));
console.log(arrayOneFiltered);
// [ { id: 1, name: 'one' } ]
Depending on the size of the array, creating a set can improve performance, as you do not need to loop over arrayTwo arrayOne.length times but only once. After that, you can look up the existence of an id in arrayTwo in constant time.
Yet, as pointed out in another answer, this is not necessary if the arrays are small (like in your example). In this case, you could also use this one-liner:
arrayOne = arrayOne.filter((elOne) => !arrayTwo.some((elTwo) => elOne.id === elTwo.id));
Here, arrayOne would need to be mutable, i.e. defined with let.
You can find it by comparing it with id.
And arrayOne must be a let.
let arrayOne = [{id: 1, name: 'one'}, {id: 2, name: 'two'}, {id: 3, name: 'three'}];
const arrayTwo = [{id: 2, name: 'two'}, {id: 3, name: 'three'}];
arrayOne = arrayOne.filter(one => !arrayTwo.find(two => one.id == two.id));
console.log(arrayOne);
const arrayOne = [{
id: 1,
name: 'one'
}, {
id: 2,
name: 'two'
}, {
id: 3,
name: 'three'
}];
const arrayTwo = [{
id: 2,
name: 'two'
}, {
id: 3,
name: 'three'
}];
const arrayTwoId = arrayTwo.map(el => (el.id)); // extract id from arrayTwo
const result = arrayOne.filter(el => !arrayTwoId.includes(el.id));
console.log(result);
Extract all the ids from the arrayTwo.
filter those objects who do not match the array of ids of arrayTwo.
Your way is correct. but you miss the not operation (!) before arrayTwo.some.
So the correct way is this:
const arrayOne = [
{id: 1, name: 'one'},
{id: 2, name: 'two'},
{id: 3, name: 'three'}
];
const arrayTwo = [
{id: 2, name: 'two'},
{id: 3, name: 'three'}
];
// Shared Items between arrayOne and arrayTwo (this what you done)
const sharedObjects = arrayOne.filter(o1 => arrayTwo.some(o2 => o1.id === o2.id));
console.log(sharedObjects);
// arrayOne - arrayTwo (this is what you want)
const arrayOneUniqueObjects = arrayOne.filter(o1 => !arrayTwo.some(o2 => o1.id === o2.id));
console.log(arrayOneUniqueObjects);
Also, You can find more details here:
bobbyhadz.com/blog/javascript-get-difference-between-two-arrays-of-objects

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 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