Merging two arrays into one that has the same amount of objects - javascript

need help with little thing. I've searched current question, but didn't find good example.
I have two arrays with same count of objects:
array1 = [{ id: 1, name: 'Johnny'}, { id: 2, name: 'Mike'}];
array2 = [{ hair: 'black'}, { hair: 'white'}];
I need
array3 = [
{ id: 1, name: 'Johnny', hair: 'black'},
{ id: 2, name: 'Mike', hair: 'white'}
]
I've tried several ways with push and [...ES6], but I always return 4 objects instead of 2.

Use Object.assign of ES6:
var array1 = [{ id: 1, name: 'Johnny'}, { id: 2, name: 'Mike'}];
var array2 = [{ hair: 'black'}, { hair: 'white'}];
var merged = array1.map((el, index) => Object.assign(el, array2[index]));
console.log(merged);

You could use Array#reduce with Array#map and Object.assign for an arbitrary count of arrays and map objects at same index in one object.
var array1 = [{ id: 1, name: 'Johnny'}, { id: 2, name: 'Mike'}];
array2 = [{ hair: 'black'}, { hair: 'white'}],
result = [array1, array2]
.reduce((r, a) => a.map((o, i) => Object.assign(r[i] || {}, o), []));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

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

Function question, angular typescript, match id values from 2 arrays to get the index from one of them

I have a two arrays, and I want to match their ID values and then get the index of that id in the second array. I know this sounds simple but I'm super new to the syntax, and I'm having a hard time picturing what this should look like. can anyone model that in simple terms?
example functionality:
var array1 = { id:2, name: 'preston'}
array2 = {
{
id: 1
name: 'john'
},
{
id: 2
name: 'bob'
}
Expected behavior
where both ids = 2, give index of array2.
returns 1
can anyone show me?
You can use findIndex on array2
Try this:
var array1 = {
id: 2,
name: 'preston'
}
var array2 = [{
id: 1,
name: 'john'
},
{
id: 2,
name: 'bob'
}
]
console.log(array2.findIndex(item => item.id === array1.id))
Or use indexOf with map if you want support for IE as well without polyfills.
var array1 = {
id: 2,
name: 'preston'
}
var array2 = [{
id: 1,
name: 'john'
},
{
id: 2,
name: 'bob'
}
]
console.log(array2.map(item => item.id).indexOf(array1.id))
Iterate over each item in array1 using forEach(). Find each item's index in array2 using findIndex().
var array1 = [{id:2, name: "preston"}];
var array2 = [{id: 1, name: "john" }, {id: 2, name: "bob" }];
array1.forEach(item => {
let index = array2.findIndex(obj => obj.id === item.id);
console.log(index);
});

How to merge three different arrays by comparing with id? in Angular 6

Arrays:
array1 = [{id:1, name:"raju"},{id:2, name:"ravi"},{id:4, name:"john"},{id:6, name:"jack"}];
array2= [{id:1, degree:"b.com"},{id:3, degree:"b.a"},{id:4, degree:"c.a"},{id:5, degree:"horticulture"}];
array3= [{id:1, age:20},{id:3, age:21},{id:6, age:27},{id:7, age:25}];
Required result is:
resultarray = [
{id:1, name: "raju", degree:"b.com",age:20},
{id:2, name: "ravi"},
{id:3, degree:"b.a", age:21},
{id:4, name:"john", degree:"c.a"},
{id:5, degree:"horticulture"},
{id:6, name:"jack", age:27},
{id:7, age:25}
]
i have tried different functions and tried for two arrays but not able to merge the object which doesnt have id to compare..
You can use reduce and destructuring
Here idea is
First merge all the arrays in one array.
Now using reduce we create id as key in op object
If id key is already there we merge the inp and op[inp.id]
If id is not there we create a new key with value inp
let array1 = [{id:1, name:"raju"},{id:2, name:"ravi"},{id:4, name:"john"},{id:6, name:"jack"}];
let array2= [{id:1, degree:"b.com"},{id:3, degree:"b.a"},{id:4, degree:"c.a"},{id:5, degree:"horticulture"}];
let array3= [{id:1, age:20},{id:3, age:21},{id:6, age:27},{id:7, age:25}];
let temp = [...array1,...array2,...array3]
let op = temp.reduce((op,inp)=>{
op[inp.id] = op[inp.id] || inp
op[inp.id] = {...op[inp.id],...inp}
return op
},{})
console.log(Object.values(op))
a possible solution:
let array1 = [{id:1, name:"raju"},{id:2, name:"ravi"},{id:4, name:"john"},{id:6, name:"jack"}];
let array2= [{id:1, degree:"b.com"},{id:3, degree:"b.a"},{id:4, degree:"c.a"},{id:5, degree:"horticulture"}];
let array3= [{id:1, age:20},{id:3, age:21},{id:6, age:27},{id:7, age:25}];
let resp = [].concat(array1, array2, array3).reduce((acc, ele) => {
let obj = acc.find(x => x.id === ele.id);
return obj ? (Object.keys(ele).forEach(x => obj[x] = ele[x]), acc) : acc.concat(ele);
}, [])
console.log(resp)
There will be better solutions than this, but this is what I've tried:
Merging the 3 arrays into one :
let array = [...array1, ...array2, ...array3]
Looping through the items and then putting the values to "object"
let object = {}
array.forEach((item) => {
object[item.id] = { ...object[item.id],...item}})
Final solution
result = Object.values(object)
object variable will contain
object = { '1': { id: 1, age: 20, name: 'raju', degree: 'b.com' },
'2': { id: 2, name: 'ravi' },
'3': { id: 3, age: 21, degree: 'b.a' },
'4': { id: 4, degree: 'c.a', name: 'john' },
'5': { id: 5, degree: 'horticulture' },
'6': { id: 6, age: 27, name: 'jack' },
'7': { id: 7, age: 25 } }
result variable will contain
result = [ { id: 1, age: 20, name: 'raju', degree: 'b.com' },
{ id: 2, name: 'ravi' },
{ id: 3, age: 21, degree: 'b.a' },
{ id: 4, degree: 'c.a', name: 'john' },
{ id: 5, degree: 'horticulture' },
{ id: 6, age: 27, name: 'jack' },
{ id: 7, age: 25 } ]

Set order to array of object in javascript

I need to find a simplest way for setting order to array of objects.
For example, there is an array:
var array = [
{id: 1, name: "Matt"},
{id: 2, name: "Jack"},
{id: 3, name: "Morgan"},
{id: 4, name: "Bruce"}
];
and I have provided
var order = [1,4,2,3];
which refers to object id property of array items.
Now I need to reorder array so it should be like:
var array = [
{id: 1, name: "Matt"},
{id: 4, name: "Bruce"},
{id: 2, name: "Jack"},
{id: 3, name: "Morgan"}
]
Use Array#sort method for sorting and inside custom sort function use Array#indexOf method to get index.
var array = [{
id: 1,
name: "Matt"
}, {
id: 2,
name: "Jack"
}, {
id: 3,
name: "Morgan"
}, {
id: 4,
name: "Bruce"
}];
var order = [1, 4, 2, 3];
array.sort(function(a, b) {
// sort based on the index in order array
return order.indexOf(a.id) - order.indexOf(b.id);
})
console.log(array);
You can also use reduce() on [1,4,2,3] array to return object where keys will be elements and values will be index of each element and then sort by that object.
var array = [
{id: 1, name: "Matt"},
{id: 2, name: "Jack"},
{id: 3, name: "Morgan"},
{id: 4, name: "Bruce"}
];
var s = [1,4,2,3].reduce((r, e, i) => {return r[e] = i, r}, {});
var result = array.sort(function(a, b) {
return s[a.id] - s[b.id];
});
console.log(result)
I guess anything that involves sort can not be more efficient than an O(2n) solution. So i would like to do this job with two reduces as follows;
var arr = [{id: 1, name: "Matt"}, {id: 2, name: "Jack"}, {id: 3, name: "Morgan"}, {id: 4, name: "Bruce"}],
order = [1,4,2,3],
lut = order.reduce((t,e,i) => (t[e] = i,t),{}),
result = arr.reduce((res,obj) => (res[lut[obj.id]] = obj, res) ,[]);
console.log(result);

Merge property from an array of objects into another based on property value lodash

I have 2 arrays of objects, they each have an id in common. I need a property from objects of array 2 added to objects array 1, if they have matching ids.
Array 1:
[
{
id: 1,
name: tom,
age: 24
},
{
id: 2,
name: tim,
age: 25
},
{
id: 3,
name: jack,
age: 24
},
]
Array 2:
[
{
id: 1,
gender: male,
eyeColour: blue,
weight: 150
},
{
id: 2,
gender: male,
eyeColour: green,
weight: 175
},
{
id: 3,
gender: male,
eyeColour: hazel,
weight: 200
},
]
Desired Outcome:
[
{
id: 1,
name: tom,
age: 24,
eyeColour: blue,
},
{
id: 2,
name: tim,
age: 25,
eyeColour: green,
},
{
id: 3,
name: jack,
age: 24,
eyeColour: hazel,
},
]
I tried using lodash _.merge function but then I end up with all properties into one array, when I only want eyeColour added.
Lodash remains a highly useful bag of utilities, but with the advent of ES6 some of its use cases are less compelling.
For each object (person) in the first array, find the object in the second array with matching ID (see function findPerson). Then merge the two.
function update(array1, array2) {
var findPerson = id => array2.find(person => person.id === id);
array1.forEach(person => Object.assign(person, findPerson(person.id));
}
For non-ES6 environments, rewrite arrow functions using traditional syntax. If Array#find is not available, write your own or use some equivalent. For Object.assign, if you prefer use your own equivalent such as _.extend.
This will merge all properties from array2 into array1. To only merge eyeColour:
function update(array1, array2) {
var findPerson = id => array2.find(person => person.id === id);
array1.forEach(person => {
var person2 = findPerson(person.id));
var {eyeColour} = person2;
Object.assign(person, {eyeColour});
});
}
Just noticed Paul answered while I was working on my answer but I'll add my very similar code anyway:
var getEyeColour = function (el) { return _.pick(el, 'eyeColour'); }
var out = _.merge(arr1, _.map(arr2, getEyeColour));
DEMO
You can use pick to get only the properties you want before merging:
var result = _.merge( arr1, _.map( arr2, function( obj ) {
return _.pick( obj, 'id', 'eyeColour' );
}));
A solution in plain Javascript
This is a more generic solution for merging two arrays which have different properties to union in one object with a common key and some properties to add.
var array1 = [{ id: 1, name: 'tom', age: 24 }, { id: 2, name: 'tim', age: 25 }, { id: 3, name: 'jack', age: 24 }, ],
array2 = [{ id: 1, gender: 'male', eyeColour: 'blue', weight: 150 }, { id: 2, gender: 'male', eyeColour: 'green', weight: 175 }, { id: 3, gender: 'male', eyeColour: 'hazel', weight: 200 }, ];
function merge(a, b, id, keys) {
var array = [], object = {};
function m(c) {
if (!object[c[id]]) {
object[c[id]] = {};
object[c[id]][id] = c[id];
array.push(object[c[id]]);
}
keys.forEach(function (k) {
if (k in c) {
object[c[id]][k] = c[k];
}
});
}
a.forEach(m);
b.forEach(m);
return array;
}
document.write('<pre>' + JSON.stringify(merge(array1, array2, 'id', ['name', 'age', 'eyeColour']), 0, 4) + '</pre>');
I was looking for the same, but I want to match Id before merging
And in my case, second array may have different number of items, finally I came with this:
var out = arr1.map(x => {
return { ...x, eyeColour: arr2.find(y => x.id === y.id)?.eyeColour }
});

Categories