compare and merge array in javascript - javascript

const arr1 = [{id:1, checked:false},{id:2, checked:false},{id:3, checked:false}]
const arr2 = [{id:1},{id:3}]
i have 2 arrays like above. i want to result should be
arr1 = [{id:1, checked:true},{id:2, checked:false},{id:3, checked:true}]
i tried with array filter, but it gives joined array
companyArr.forEach(citem => {
mapItem.forEach(mitem => {
companyArr.push({
Id: citem.Id,
CompanyName: citem.CompanyName,
isChecked: (mitem.company_id === citem.Id)
})
})
})

You could make a Set which keeps all your ids from each object in arr2, and then use .map() on arr1 to check the checked values based on whether the set has the current objects id:
const arr1 = [{id:1, checked:false},{id:2, checked:false},{id:3, checked:false}]
const arr2 = [{id:1},{id:3}];
const lut = new Set(arr2.map(({id}) => id));
const res = arr1.map(o => ({...o, checked: lut.has(o.id)}))
console.log(res);
.as-console-wrapper { max-height: 100% !important; top: 0; } /* ignore */
Note: I've created a set here for efficient lookup, however, you could use .some() on arr2 if you wish in the .map() as well, but this would have performance drawbacks for large data sets:
const arr1 = [{id:1, checked:false},{id:2, checked:false},{id:3, checked:false}]
const arr2 = [{id:1},{id:3}];
const res = arr1.map(o => ({...o, checked: arr2.some(({id}) => id === o.id)}));
console.log(res);
.as-console-wrapper { max-height: 100% !important; top: 0; } /* ignore */

you could use Array#map for recreate the array .And Array#findIndex for find the first array value exist on 2nd array .And use Spread operator for easy to split the object
const arr1 = [{id:1, checked:false},{id:2, checked:false},{id:3, checked:false}]
const arr2 = [{id:1},{id:3}]
let res = arr1.map(a=> ({...a,checked: arr2.findIndex(({id}) => id == a.id) > -1}));
console.log(res)

You can use map and find for that.
const arr1 = [{ id: 1, checked: false }, { id: 2, checked: false }, { id: 3, checked: false }]
, arr2 = [{ id: 1 }, { id: 3 }]
, result = arr1.map(el => ({ ...el, checked: !!arr2.find(({ id }) => id === el.id) }));
console.log(result);

Related

convert array into given type of array of object

I have an array of type:-
const arr = ['abc','def','ghi'];
but I want this array in the form of
const arr2 = [
{value: 'abc'},
{value: 'def'},
{value: 'ghi'},
];
I am not getting the idea to do it.
use a map function to generate a new array with the type you want
for your reference, Array.prototype.map()
const arr=['abc','def','ghi'];
const arr2 = arr.map(item => ({value: item}));
console.log(arr2);
You can try using Array.prototype.map():
The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.
var arr = ['abc','def','ghi'];
arr = arr.map(value => ({value}));
console.log(arr);
You can use map to transform each item of an array to another value.
const arr = ['abc', 'def', 'ghi'];
const arr2 = arr.map(value => ({ value: value })
// const arr2 = [
// { value: "abc" },
// { value: "def" },
// { value: "ghi" }
// ];
If you want to be clever you can simplify this to
const arr2 = arr.map(value => ({ value })
See Array.prototype.map
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
More elegant way that I prefer:
Array.from(arr, (v) => {return {value: v};})

Merge array with underscore by keys

I have 2 arrays :
[{id:1,name:"name"},{id:2,name:"name2"} ,{id:3,name:"name3"}]
[{id:1,date:"123"},{id:2,date:"456"}]
Array 1 should be updated only if the id is equal :
So the array 1 will looks like
It should not create a new array . Only update the array 1 based on array 2
[{id:1,name:"name",date:"123"},{id:2,name:"name2",date:"456"} ,{id:3,name:"name3"}]
I managed to do that with for loop on array2 and inside the for filter like the following :
._filter(array1,function(item){
If(item.id=array2.id)
Do smth and update the array1.date
})
How do I doing that in he best way ? Using underscore.js
You can do something like this:
Iterate over array1 and check if the id of each item exists in array2 by using the some() method.
var arr1 = [{id:1,name:"name"},{id:2,name:"name2"} ,{id:3,name:"name3"}];
var arr2 = [{id:1,date:"123"},{id:2,date:"456"}];
var missing = [];
arr1.forEach( (item1, i) => {
var isExist = arr2.some(item2 => item2.id === item1.id)
if(!isExist) {
missing.push(i);
}
})
missing.forEach(item => {
arr2.push(arr1[item]);
})
console.log(arr2);
reference for some()
Try this :
var a = [{id:1,name:"name"},{id:2,name:"name2"} ,{id:3,name:"name3"}] ;
var b = [{id:1,date:"123"},{id:2,date:"456"}] ;
var i = 0, j = 0 ;
while( i < a.length ) {
j = 0 ;
while( j < b.length) {
if ( a[i].id === b[j].id )
Object.assign( a[i] , b[j] );
j++;
}
i++;
}
console.log(a) ;
You can use forEach to iterate over the second array and use findIndex to get the matched element from first array. If the id matches then update the object in the first array
let arr1 = [{
id: 1,
name: "name"
}, {
id: 2,
name: "name2"
}, {
id: 3,
name: "name3"
}]
let arr2 = [{
id: 1,
date: "123"
}, {
id: 2,
date: "456"
}]
arr2.forEach(function(acc) {
let findArry1Index = arr1.findIndex(function(item) {
return item.id === acc.id;
});
if (findArry1Index !== -1) {
arr1[findArry1Index].date = acc.date;
}
});
console.log(arr1)
You can do it using native language like this:
const arr1 = [{id:1,name:"name"},{id:2,name:"name2"} ,{id:3,name:"name3"}];
const arr2 = [{id:1,date:"123"},{id:2,date:"456"}];
arr1.forEach((ele) => {
const match = arr2.find(item => ele.id === item.id) || {};
Object.assign(ele, match);
});
console.log(arr1);
var a = [{id:1,name:"name"},{id:2,name:"name2"} ,{id:3,name:"name3"}];
var b = [{id:1,date:"123"},{id:2,date:"456"}];
a = _.map(a, function(e) { return _.extend(e, _.findWhere(b, {id: e.id})); });
a results in:
0: {id: 1, name: "name", date: "123"}
1: {id: 2, name: "name2", date: "456"}
2: {id: 3, name: "name3"}
However, I guess this qualifies as "creating a new array"? Maybe it can serve as an inspiration though ¯\_(ツ)_/¯
You can use underscore's indexBy function to index your second array by id, and then simply use Object.assign(...) to update your first array's elements with their corresponding match by performing a lookup in the indexed elements object.
let arr1 = [{id:1, name:"name"}, {id:2, name:"name2"}, {id:3, name:"name3"}]
let arr2 = [{id:1, date:"123"}, {id:2, date:"456"}]
const arr2Groups = _.indexBy(arr2, e => e.id);
arr1.forEach(e => Object.assign(e, arr2Groups[e.id] || {}));
console.log(arr1);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>

Javascript how to join two arrays having same property value?

How do I join arrays with the same property value? I cannot map it because it has different indexes.
var array1 = [
{'label':"label1",'position':0},
{'label':"label3",'position':2},
{'label':"label2",'position':1},
];
var array2 = [
{'label':"label1",'value':"TEXT"},
{'label':"label2",'value':"SELECT"}
];
expected output:
var array3 = [
{'label':"label1",'value':"TEXT",'position':0},
{'label':"label2",'value':"SELECT", 'position':1}
];
This is what I did, I cannot make it work,
var arr3 = arr1.map(function(v, i) {
return {
"label": v.label,
"position": v.position,
"value": arr2[?].value
}
});
I think you can use array#reduce to do something like this perhaps:
var array1 = [
{'label':"label1",'position':0},
{'label':"label3",'position':2},
{'label':"label2",'position':1},
];
var array2 = [
{'label':"label1",'value':"TEXT"},
{'label':"label2",'value':"SELECT"}
];
var array3 = array2.reduce((arr, e) => {
arr.push(Object.assign({}, e, array1.find(a => a.label == e.label)))
return arr;
}, [])
console.log(array3);
You could take a Map and check the existence for a new object.
var array1 = [{ label: "label1", position: 0 }, { label: "label3", position: 2 }, { label: "label2", position: 1 }],
array2 = [{ label: "label1", value: "TEXT" }, { label: "label2", value: "SELECT" }],
map = array1.reduce((m, o) => m.set(o.label, o), new Map),
array3 = array2.reduce((r, o) => {
if (map.has(o.label)) {
r.push(Object.assign({}, o, map.get(o.label)));
}
return r;
}, []);
console.log(array3);
.as-console-wrapper { max-height: 100% !important; top: 0; }
As per the effort, we take an assumption that array1 will be having all the labels that are in array2.
Based on that first, create a map for array2and with key being labels. Post that, filter out array1 items which have labels existing in the map and then finally merging the objects of the filtered array and its corresponding values in map extracted from array2.
var array1 = [{'label':"label1",'position':0},{'label':"label3",'position':2},{'label':"label2",'position':1}];
var array2 = [{'label':"label1",'value':"TEXT"},{'label':"label2",'value':"SELECT"}];
let map = array2.reduce((a,{label, ...rest}) => Object.assign(a,{[label]:rest}),{});
let result = array1.filter(({label}) => map[label]).map(o => ({...o, ...map[o.label]}));
console.log(result);
Also, in the above snippet, you can improve the performance further by using Array.reduce against filter and map functions to retrieve the result.
var array1 = [{'label':"label1",'position':0},{'label':"label3",'position':2},{'label':"label2",'position':1}];
var array2 = [{'label':"label1",'value':"TEXT"},{'label':"label2",'value':"SELECT"}];
let map = array2.reduce((a,{label, ...rest}) => Object.assign(a,{[label]:rest}),{});
let result = array1.reduce((a,o) => {
if(map[o.label]) a.push({...o, ...map[o.label]});
return a;
}, []);
console.log(result);
If you don't know in advance which array(s) will have their labels be a subset of the other (if any), here's a method that allows for either array1 or array2 to have labels that the other array lacks. Use reduce over array1, finding the matching label in array2 if it exists:
var array1 = [
{'label':"label1",'position':0},
{'label':"label3",'position':2},
{'label':"label2",'position':1},
];
var array2 = [
{'label':"label1",'value':"TEXT"},
{'label':"label2",'value':"SELECT"}
];
const output = array1.reduce((a, { label, position }) => {
const foundValueObj = array2.find(({ label: findLabel }) => findLabel === label);
if (!foundValueObj) return a;
const { value } = foundValueObj;
a.push({ label, value, position });
return a;
}, []);
console.log(output);
See Array.prototype.map() and Map for more info.
// Input.
const A = [{'label':"label1",'position':0},{'label':"label3",'position':2},{'label':"label2",'position':1}]
const B = [{'label':"label1",'value':"TEXT"},{'label':"label2",'value':"SELECT"}]
// Merge Union.
const mergeUnion = (A, B) => {
const mapA = new Map(A.map(x => [x.label, x]))
return B.map(y => ({...mapA.get(y.label), ...y}))
}
// Output + Proof.
const output = mergeUnion(A, B)
console.log(output)
This works.
Approach: Concatenate the objects with same label, using Object.assign()
var array1 = [{'label':"label1",'position':0},{'label':"label3",'position':2},{'label':"label2",'position':1}];
var array2 = [{'label':"label1",'value':"TEXT"},{'label':"label2",'value':"SELECT"}];
var result = [];
array2.forEach(function(value, index){
result.push(Object.assign({},array1.find(function(v,i){return v.label==value.label}),value));
});
console.log(result)
Im not good with javascript,but you could also do this
var array1 = [
{'label':"label1",'position':0},
{'label':"label3",'position':2},
{'label':"label2",'position':1},
];
var array2 = [
{'label':"label1",'value':"TEXT"},
{'label':"label2",'value':"SELECT"}
];
var array3=[];
for(var i=0;i<array1.length;i++)
{
for(var x=0;x<array2.length;x++)
{
console.log(array1[i]['label'] == array2[x]['label']);
if(array1[i]['label'] == array2[x]['label']){
array3.push({label:array1[i]['label'],value:array2[x]['value'],position:array1[i]['position']});
}
}
}
console.log(array3);

es6 merge two array of objects and override the existing object

I have 2 array of objects:
const arr1 = [{'id':'1' 'value':'yes'}, {'id':'2', 'value':'no'}];
const arr2 = [{'id':'2', 'value':'yes'}];
So, if I try and merge these 2 arrays the result should be:
arrTemp = [{'id':'1', 'value':'yes'}, {'id':'2', 'value':'yes'}];
Basically, it should work similar to Object.assign(), but no matter what I try it does not work. Could anyone please help me in this ?
I modified the data structure. Is it possible to merge them now and get the output.
Thanks
This is how you can get the job done with ES6 spread, reduce and Object.values.
const arr1 = [{
'id': '1',
'value': 'yes'
}, {
'id': '2',
'value': 'no'
}];
const arr2 = [{
'id': '2',
'value': 'yes'
}];
const result = Object.values([...arr1, ...arr2].reduce((result, {
id,
...rest
}) => {
result[id] = {
...(result[id] || {}),
id,
...rest
};
return result;
}, {}));
console.log(result);
const result = Object.entries(Object.assign({}, ...arr1,...arr2)).map(([key, value]) => ({[key]:value}));
You could spread (...) the arrays into one resulting object ( via Object.assign) and then map its entries to an array again.
You could work with a valid ES6 data structure like a map for example:
const 1 = { 1: { string: 'yes' }, 2: { string: 'no' } }
const 2 = { 2: { string: 'yes' }, 3: { string: 'no' } }
const 3 = { ...1, ...2}
This will override your first argument with the second one or just combine them where possible.
Just try it out in your browser it's a lot easier and enhances performance since you will never have to use findById() which is an expensive operation.
In javascript, arrays are simply objects indexed by numbers starting from 0.
So when you use Object.assign on arr1 and arr2 you will override the first item in the arr1 with the first item in arr2 because they are both indexed under the key 0.
your result will be:
[
{ '2': 'yes' },
{ '2': 'no' }
]
(or in object syntax:)
{
0: { '2': 'yes' },
1: { '2': 'no' }
}
Instead of using arrays, you could create an object indexed by the number string (which is how you seem to be thinking of the array in any case).
So you could change your original data structure to make the job easier:
const arr1 = {
'1': 'yes',
'2': 'no'
};
const arr2 = {
'2': 'yes'
};
const result = Object.assign(arr1, arr2);
You could take a Map as reference to the new assigned object in the result array and build first a new array with a copy of the objects and then iterate the second array and update the objects with the same key.
var array1 = [{ 1: 'yes' }, { 2: 'no' }],
array2 = [{ 2: 'yes' }],
getKey = o => Object.keys(o)[0],
map = new Map,
result = array1.map(o => (k => map.set(k, Object.assign({}, o)).get(k))(getKey(o)));
array2.forEach(o => Object.assign(map.get(getKey(o)), o));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Array reduce could come in handy is this case. See example below:
[...arr1, ...arr2].reduce((acc, item) => {
const updated = acc.find(a => a.id === item.id)
if (!updated) {
acc.push(item)
} else {
const index = acc.indexOf(updated)
acc[index] = { ...item, ...acc[index] }
}
return acc
}, [])
simple way to add with exist array of object:
const arr1 = [{ "name":"John", "age":30, "car":"toyata" }];
const arr2 = [{ "name":"Ales", "age":40, "car":"Nissan" }];
Array.prototype.push.apply(arr1, arr2);
Result:=>
console.log(arr1)
For anyone finding this answer at a later point in time. There are a couple of ways that you could want this to work exactly, but you could filter all adjusted elements in the first array, and then combine it with the second array.
const arr3 = [...arr1.filter(item1 => !arr2.find(item2 => item1.id === item2.id)), ...arr2]
Alternatively, you could update the elements in the first array, and then filter them from the second array instead.
You cannot use array.prototype map because the key of arr1 and arr2 have the same value '2'.
You should use something like this
for (var i = 0, l = arr1.length; i < l; i++) {
var key = Object.keys(arr1[i]);
if (!arr2[key]) { arr2[key] = []; }
arr2[key].push(arr1[i][key]);
}
Regards

Combine several arrays into an array of objects in JavaScript

Say I have three arrays depicting some names, number of books read and how awesome these people [in names] are:
let names = ["Mary", "Joe", "Kenan"];
let numberOfBooks = [2, 1, 4];
let awesomenessLevel = ["pretty cool", "meh", "super-reader"];
I'm trying to use .reduce() to bring them together to create an array of objects containing the relevant index in each array, but I am failing miserably:
let people = [
{
name: "Mary",
noOfBooks: 2,
awesomeness: "pretty cool"
},
{
name: "Joe",
noOfBooks: 1,
awesomeness: "meh"
},
{
name: "Kenan",
noOfBooks: 4,
awesomeness: "super-reader"
}
]
I got it with reduce as well:
let arrFinal = [];
names.reduce(function(all, item, index) {
arrFinal.push({
name: item,
noOfBooks: numberOfBooks[index],
awesomeness: awesomenessLevel[index]
})
}, []);
You could do it with map, like this:
let result = names.map( (v, i) => ({
name: names[i],
noOfBooks: numberOfBooks[i],
awesomenessLevel: awesomenessLevel[i]
}));
let names = ["Mary", "Joe", "Kenan"];
let numberOfBooks = [2, 1, 4];
let awesomenessLevel = ["pretty cool", "meh", "super-reader"];
let result = names.map( (v, i) => ({
name: names[i],
noOfBooks: numberOfBooks[i],
awesomenessLevel: awesomenessLevel[i]
}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
map works better than reduce in this case, because the number of elements you have in the names array (or any of the two others) is the same as the number of elements you need in the output. In that case it is more natural to use map.
Use map to create a 1-to-1 mapping between the input arrays and the output arrays.
let people = names.map(function (e, i) {
return {name:e, noOfBooks:numberOfBooks[i],awesomeness: awesomenessLevel[i]};
});
let names = ["Mary", "Joe", "Kenan"];
let numberOfBooks = [2, 1, 4];
let awesomenessLevel = ["pretty cool", "meh", "super-reader"];
let people = names.map(function (e, i) {
return {name:e, noOfBooks:numberOfBooks[i],awesomeness: awesomenessLevel[i]};
});
console.log(people);
You could use a dynamic approach by combining all arrays to one object and use the key names as property names for the result objects in the array
let names = ["Mary", "Joe", "Kenan"],
numberOfBooks = [2, 1, 4],
awesomenessLevel = ["pretty cool", "meh", "super-reader"],
object = { name: names, noOfBooks: numberOfBooks, awesomeness: awesomenessLevel },
result = Object.keys(object).reduce((r, k) =>
(object[k].forEach((a, i) =>
(r[i] = r[i] || {})[k] = a), r), []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Categories