Intersect 3 arrays in Javascript - With snippet - javascript

I'm trying to intersect array1 and array2 and find the elements that contain the same name.
Then on array3 I only want to keep the elements that exist on the first intersection by name.
I'm stuck here, I just get true and falses. Any help?
const array1 = [{
name: 'John'
}];
const array2 = [{
name: 'Elisa'
}, {
name: 'John'
}];
const array3 = [{
name: 'Elisa',
age: 10
}, {
name: 'John',
age: 23
}, {
name: 'Maria',
age: 30
}];
const intersectArray = array1.map(elem1 => array2.map(elem2 => elem1.name === elem2.name));
console.log(intersectArray);
const filteredArray = array3.map(elem3 => intersectArray.map(elem => elem.name === elem3.name));
console.log(filteredArray);
The expected result should be:
{ name: 'John', age: 23 }

You can just check against both arrays, instead of first creating an intersection:
const array1 = [{ name: 'John' }];
const array2 = [{ name: 'Elisa' }, { name: 'John' }];
const array3 = [{ name: 'Elisa', age: 10 }, { name: 'John', age: 23 }, { name: 'Maria', age: 30 }];
const result = array3.filter(x =>
array1.some(a => a.name === x.name) &&
array2.some(a => a.name === x.name))
console.log(result);

To do what you require you can use filter() to return only the elements which meet certain criteria. In your case, you can find() within the other array if a matching name is found.
The same logic can be used for both steps:
const array1 = [{ name: 'John' }];
const array2 = [{ name: 'Elisa' }, { name: 'John' }];
const array3 = [{ name: 'Elisa', age: 10 }, { name: 'John', age: 23 }, { name: 'Maria', age: 30 }];
const intersectArray = array1.filter(o1 => array2.find(o2 => o1.name == o2.name));
console.log(intersectArray);
const filteredArray = array3.filter(o3 => intersectArray.find(ia => o3.name === ia.name));
console.log(filteredArray);

If you want to grab the intersection between three arrays, you can filter the first array and find a similar item in the second array with some.
const
intersection = (a, b, f) => a.filter(x => b.some(y => f(x) === f(y))),
intersection2 = (f, ...a) => a.reduce((r, b) => intersection(r, b, f));
const
arr1 = [{ name: 'John' }],
arr2 = [{ name: 'Elisa' }, { name: 'John' }],
arr3 = [{ name: 'Elisa', age: 10 }, { name: 'John', age: 23 }, { name: 'Maria', age: 30 }];
const
getName = ({ name }) => name,
inter1 = intersection(arr3, intersection(arr2, arr1, getName), getName),
inter2 = intersection2(getName, arr3, arr2, arr1);
console.log(inter1); // Nested calls
console.log(inter2); // Reduction
.as-console-wrapper { top: 0; max-height: 100% !important; }

Related

Copy values from multiple keys from array of object

I want to copy value of name and age into another array, below code is working fine, But I wanted to know better way to do it.
const users = [
{ id: 0, name: 'John', age:34 },
{ id: 1, name: 'Wayne', age:44 },
{ id: 2, name: 'David', age:24 },
];
let values=[];
users && users.map(user => {
values.push(user['name'])
values.push(user['age'])
})
console.log(values);
output
['John', 34, 'Wayne', 44, 'David', 24]
You can bind each items to an array containing both its name and age and then flattern these arrays.
This can be done using Array#FlatMap
const users = [
{ id: 0, name: 'John', age:34 },
{ id: 1, name: 'Wayne', age:44 },
{ id: 2, name: 'David', age:24 },
];
const nameAndAges = users.flatMap(user => [user.name, user.age])
console.log(nameAndAges)
Your solution looks good, this can be also solved in different ways, I guess you may want to create function for handling this.
const users = [
{ id: 0, name: 'John', age: 34 },
{ id: 1, name: 'Wayne', age: 44 },
{ id: 2, name: 'David', age: 24 },
];
const result = mapArrayToProps(users, ['name', 'age']);
function mapArrayToProps(arr, props) {
return arr.flatMap(obj => mapObjectToProps(obj, props));
}
function mapObjectToProps(obj, props) {
return props.map(prop => obj[prop])
}
console.log(result);

Removing not matching obj from old array and replace matching obj from new array with old matching obj

I cant figure out how to do this...
const arr1 = [{ name: 'peter' }, { name: 'sam', id: 1 }, { name: 'mark' }];
const arr2 = [{ name: 'sam' }, { name: 't' }, { name: 'george' }];
Desired outcome:
const arr2 = [{ name: 'sam', id: 1 }, { name: 't' }, { name: 'george' }];
If you want the previous item I would do this:
const arr1 = [{
name: 'peter'
}, {
name: 'sam',
id: 1
}, {
name: 'mark'
}];
const arr2 = [{
name: 'sam'
}, {
name: 't'
}, {
name: 'george'
}];
const result = arr2.map(item => {
const previousItem = arr1.find(i => i.name === item.name)
if (previousItem) {
return previousItem
}
return item
})
console.log(result);
However, if you want to combine the old and new data, I would recommend spreading the data together, like so:
const arr1 = [{
name: 'peter'
}, {
name: 'sam',
id: 1
}, {
name: 'mark'
}];
const arr2 = [{
name: 'sam'
}, {
name: 't'
}, {
name: 'george'
}];
const result = arr2.map(item => {
const previousItem = arr1.find(i => i.name === item.name)
if (previousItem) {
return {
...previousItem,
...item
}
}
return item
})
console.log(result);
Both allude to the same result here, but you would get different results if arr2's "Sam" object had an additional key "age" on it...
In this example, the second snippet would keep the "age" key because the spread (...) operation combines the two objects together.
You can try this.
const arr1 = [{ name: 'peter' }, { name: 'sam', id: 1 }, { name: 'mark' }];
const arr2 = [{ name: 'sam' }, { name: 't' }, { name: 'george' }];
const result = [];
const res1 = arr2.map((item, i) => {
let index = arr1.findIndex((x) => x.name === item.name);
if ( index > -1 )
result.push(arr1[index]);
else
result.push(item);
})
console.log(result);

How to loop through an object and then use array methods on its keys?

I see that all the loops for objects returns the key as string and the value, but I want to operate on the keys of the object itself. If I have this object:
const data = {
person1: [
{ id: 1, name: Mike, age: 24 },
{ id: 2, name: Bob, age: 31 }
],
person2: [
{ id: 3, name: Christin, age: 21 },
{ id: 4, name: Michelle, age: 33 }
],
}
const removePersonById = (id) => {
// Check which person the id belongs to and remove that person
const persons = Object.keys(data).map(person => ...)
}
I wanted to loop through data and run .includes on each person in order to remove them by the id, but I am at a loss on how to do that.
You can loop through all keys and delete that the person you want by id using the filter() method
const removePersonById = (id) => {
var all = Object.keys(data);
for(let person of all){
data[person] = data[person].filter(a => a.id!=id);
}
}
You could get the values and find the index. Then splice.
const
removePersonById = id => {
Object.values(data).forEach(a => {
const index = a.findIndex(o => o.id === id);
if (index !== 0) a.splice(index, 1);
});
};
You could use .some()
const data = {
person1: [
{ id: 1, name: "Mike", age: 24 },
{ id: 2, name: "Bob", age: 31 }
],
person2: [
{ id: 3, name: "Christin", age: 21 },
{ id: 4, name: "Michelle", age: 33 }
],
}
const removePersonById = (id) => {
// Check which person the id belongs to and remove that person
Object.keys(data).map(person => {
if (data[person].some(p => p.id === id)) delete data[person];
})
}
removePersonById(3)
console.log(data)
Use Object.entries() so you can iterate over the keys and values together. Then you can test the value to see if the id is found.
Then use the delete operator to remove that key from the object.
const removePersonById = id => {
delete data[id];
};
const data = {
person1: [
{ id: 1, name: "Mike", age: 24 },
{ id: 2, name: "Bob", age: 31 }
],
person2: [
{ id: 3, name: "Christin", age: 21 },
{ id: 4, name: "Michelle", age: 33 }
],
};
const removePersonById = (id) =>
Object.entries(data).forEach(([key, value]) => {
if (value.some(({id: personid}) => personid == id)) {
delete data[key];
}
});
removePersonById(3);
console.log(data);
let data = {
person1: [
{ id: 1, name: "Mike", age: 24 },
{ id: 2, name: "Bob", age: 31 }
],
person2: [
{ id: 3, name: "Christin", age: 21 },
{ id: 4, name: "Michelle", age: 33 }
],
}
const removePersonById = (id) => {
// Check which person the id belongs to and remove that person
data = Object.keys(data).reduce((acc,key) => {
if(data[key].some(person=>person.id===id)) return acc
acc[key]= data[key]
return acc
}, {})
console.log(`Remove person with ID ${id}: `,data)
}
removePersonById(1)

How to add property to json file with map function?

Hello I m trying to map through a json file and add a new property to every object in it.
DATA.JSON
const arr = [
{
index: 0,
name: "John",
hair: "Brown",
},
{
index: 1,
name: "Bob",
hair: "Blonde",
},
];
APP.JS
const data = require("./data.json");
const items = data.map((item) => {
return ????
});
I want to map through the array, and add a "age" property to every index with a value of 30 or even just an empty value would be ok. with result something like this:
RESULT
const a =
[
{
index: 0,
name: "John",
hair: "Brown",
age: 30
},
{
index: 1,
name: "Bob",
hair: "Blonde",
age: 30
},
];
const arr = [
{
index: 0,
name: "John",
hair: "Brown",
},
{
index: 1,
name: "Bob",
hair: "Blonde",
},
];
const result = arr.map((obj) => {
return { ...obj, age: 30 };
});
console.log(result);
You can also make it one-liner
const result = arr.map((obj) => ({ ...obj, age: 30 }));
If you want to print only hair of each index then
const arr = [
{
index: 0,
name: "John",
hair: "Brown",
},
{
index: 1,
name: "Bob",
hair: "Blonde",
},
];
const result = arr.map((obj) => {
return { ...obj, age: 30 };
});
const hairs = result.map((o) => o.hair);
console.log(hairs); // Printing as an array
console.log(hairs.toString()); // Printing as comma separated value
Hello you could do something like this:
const data = [
{
index:0,
name: "John",
hair: "Brown",
},
{
index:1,
name: "Bob",
hair: "Blonde",
},
];
const newData = data.map(item => ({
...item,
newProp: 'hello world',
}));
// Print whole data:
console.log(newData);
// Filter specific properties
const hair = newData.map(item => item['hair'])
console.log('only hair ->', hair);
Side note, you don't need the index property in the object since you can get it while looping.
map(currentItem, index) Docs
If you want to print specific properties of the object you can do as such:
console.log(newData.map(item => item['hair']));

Javascript filter array based on another array of object

I am trying to merge the two arrays based on Arr1 values. If the array 2 doesn't has the respective value in array1, it should return as empty object with values. Below are the two arrays:
Arr1 = [{
name: "raj",
age: 20
}, {
name: "ravi",
age: 40
}];
Arr2 = ['raj', 'ravi', 'arnold'];
Javascript Code is,
let result = Arr1.filter(o1 => Arr2.some(o2 => o2 === o1.name));
I am getting the result as below,
result = [{
name: "raj",
age: 20
}, {
name: "ravi",
age: 40
}];
But expected array should be,
[{
name: "raj",
age: 20
}, {
name: "ravi",
age: 40
}, {
name: "arnold",
age: null,
available: no
}];
Any suggestions?
You can use Array#map along with Array#find to obtain your expected result.
let Arr1 = [{
name: "raj",
age: 20
}, {
name: "ravi",
age: 40
}];
let Arr2 = ['raj', 'ravi', 'arnold'];
let result = Arr2.map(x=>
Arr1.find(({name})=>name===x)??{name:x,age:null,available: 'no'}
);
console.log(result);
I suggest a different approach and take an object for the given data and map the wanted names for eithe the given data or a new object.
This approach has a better big O, becaus it take a hash table and works fast for great data.
const
array1 = [{ name: "raj", age: 20 }, { name: "ravi", age: 40 }],
array2 = ['raj', 'ravi', 'arnold'],
data = array1.reduce((r, o) => (r[o.name] = o, r), {}),
result = array2.map(name => data[name] || { name, age: null, available: 'no' });
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Categories

Resources