How to compare and change the array of object value in javascript - javascript

I have two arrays of objects and want to compare the name and value of them.
const array1 = [
{
name: 'John',
value: null
},
{
name: 'Peter',
value: null
}
]
const array2 = [
{
name: 'John',
value: '0'
}
]
If property name array2 exists on array1 then change the value of name with '0' else do nothing.
The result I expect is :
[
{
"name": "John",
"value": "0"
},
{
"name": "Peter",
"value": null
]
Can anyone show me how to do that?

You can use two forEach() loop for that:
const array1 = [
{
name: 'John',
value: null
},
{
name: 'Peter',
value: null
},
{
name: 'Mike',
value: null
}
]
const array2 = [
{
name: 'John',
value: '0'
},
{
name: 'Mike',
value: '0'
}
]
array2.forEach((item2) => {
array1.forEach((item1) => {
if(item1.name === item2.name){
item1.value = item2.value;
}
});
});
console.log(array1);

its simple :
array1.forEach(record1 => {
array2.forEach(record2 => {
if (record1.name === record2.name) {
record1.value = "0";
}
});
});

You can also map the first array and use find.
Please note this version of the code won't alter/mutate array1's content.
const array1 = [
{
name: 'John',
value: null
},
{
name: 'Peter',
value: null
}
];
const array2 = [
{
name: 'John',
value: '0'
}
];
const result = array1.map(item1 => {
const newItem = {...item1}
if(array2.find(item2 => item2.name === item1.name)) {
newItem.value = 0;
}
return newItem;
});
console.log(result);

its very simple:
you can user the below code :
array2.forEach(
function(parent){
array1.find(function(child)
{
if(child.name==parent.name){
child.value=0;
}
})
}
);

Try this:
const array1 = [
{
name: 'John',
value: null
},
{
name: 'Peter',
value: null
},
{
name: 'Mike',
value: null
}
]
const array2 = [
{
name: 'John',
value: '0'
},
{
name: 'Mike',
value: '0'
}
]
var array = array1.map(x=>{
if(array2.some(function (value) { return value.name === x.name })){
x.value = 0;
}
return x;
})

Related

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

Filter out array using another array of objects

I am having two arrays
const selected = [];
const current = [
{ id: 1, name: "abc" },
{ id: 2, name: "def" }
];
const result = []
I need to compare these two arrays and the result should only have the single entry instead of duplicates. In the above example result should have the following output.
Also items in the selected should be taken into consideration and should be in the beginning of the result
result = [
{ id: 1, name: "abc" },
{ id: 2, name: "def" }
];
Also when the input is following
const selected = [ {id:5, name: "xyz" }];
const current = [
{ id: 1, name: "abc" },
{ id: 2, name: "def" }
];
result = [[
{ id: 5, name: "xyz" },
{ id: 1, name: "abc" },
{ id: 2, name: "def" }
];
Also when the input is following
const selected = [ {id:1, name: "abc" }, {id:4, name: "lmn" }];
const current = [
{ id: 1, name: "abc" },
{ id: 2, name: "def" }
];
result = [[
{ id: 1, name: "abc" },
{ id: 4, name: "lmn" }
{ id: 2, name: "def" }
];
Note the comparison should be made using name field
Code that I tried
const res = [...(selected || [])].filter((s) =>
current.find((c) => s.name === c.name)
);
Sandbox: https://codesandbox.io/s/nervous-shannon-j1vn5k?file=/src/index.js:115-206
You could get all items and filter the array by checking the name with a Set.
const
filterBy = (key, s = new Set) => o => !s.has(o[key]) && s.add(o[key]),
selected = [{ id: 1, name: "abc" }, { id: 1, name: "lmn" }],
current = [{ id: 1, name: "abc" }, { id: 2, name: "def" }],
result = [...selected, ...current].filter(filterBy('name'));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Loop through selected, and if there is no object in current with a name that matches the name of the object in the current iteration push it into current.
const selected=[{id:1,name:"abc"},{id:6,name:"def"},{id:4,name:"lmn"}];
const current=[{id:1,name:"abc"},{id:2,name:"def"}];
for (const sel of selected) {
const found = current.find(cur => cur.name === sel.name);
if (!found) current.push(sel);
}
console.log(current);
This is a good use for .reduce, avoids multiple loops/finds and doesn't need filtering with side-effects.
const selected = [ {id:1, name: "abc" }, {id:4, name: "lmn" }];
const current = [
{ id: 1, name: "abc" },
{ id: 2, name: "def" }
];
const result = Object.values(
[...selected, ...current].reduce((obj, item) => {
obj[item.name] = obj[item.name] || item;
return obj;
}, {})
)
console.log(result);

What is an alternative way to update an array of objects?

I have a array of objects. I want to update an object using id.
I am able to do using the map function. Is there an alternative way or more efficient way to update the array?
Here is my code:
https://stackblitz.com/edit/js-xgfwdw?file=index.js
var id = 3
var obj = {
name: "test"
}
let arr = [{
name: "dd",
id: 1
}, {
name: "dzxcd",
id: 3
}, {
name: "nav",
id: 5
}, {
name: "hhh",
id: 4
}]
function getUpdated(obj, id) {
var item = [...arr];
const t = item.map((i) => {
if(i.id==id){
return {
...obj,
id
}
}else {
return i;
}
})
return t
}
console.log(getUpdated(obj,id))
The expected output is correct but I want to achieve the same functionality using an alternative way.
[{
name: "dd",
id: 1
}, {
name: "test",
id: 3
}, {
name: "nav",
id: 5
}, {
name: "hhh",
id: 4
}]
you are in the correct way, basically the bad thing that you are doing is creating new arrays [...arr], when map already gives you a new array.
other things to use, may be the ternary operator and return directly the result of the map function
check here the improvedGetUpdate:
var id = 3;
var obj = {
name: "test"
};
let arr = [{
name: "dd",
id: 1
}, {
name: "dzxcd",
id: 3
}, {
name: "nav",
id: 5
}, {
name: "hhh",
id: 4
}]
function getUpdated(obj, id) {
var item = [...arr];
const t = item.map((i) => {
if (i.id == id) {
return {
...obj,
id
}
} else {
return i;
}
})
return t
}
improvedGetUpdate = (obj, id) => arr.map(i => {
return i.id !== id ? i : {
...obj,
id
}
})
console.log(getUpdated(obj, id))
console.log(improvedGetUpdate(obj, id))
var id = 3
var obj = {
name: "test"
}
let arr = [{
name: "dd",
id: 1
}, {
name: "dzxcd",
id: 3
}, {
name: "nav",
id: 5
}, {
name: "hhh",
id: 4
}]
const result = arr.map((el) => el.id === id ? {...obj, id} : el)
console.log(result);
Use splice method which can be used to update the array too:
var obj = {
id: 3,
name: "test"
}
let arr = [{
name: "dd",
id: 1
}, {
name: "dzxcd",
id: 3
}, {
name: "nav",
id: 5
}, {
name: "hhh",
id: 4
}]
arr.splice(arr.findIndex(({id}) => id === obj.id), 0, obj);
console.log(arr);
#quirimmo suggested short code.
I suggest fast code.
var id = 3;
var obj = {
id: 3,
name: "test"
}
let arr = [{
name: "dd",
id: 1
}, {
name: "dzxcd",
id: 3
}, {
name: "nav",
id: 5
}, {
name: "hhh",
id: 4
}]
var arr2 = [...arr];
console.time('⏱');
arr.splice(arr.findIndex(({id}) => id === obj.id), 0, obj);
console.timeEnd('⏱');
console.time('⏱');
for (let item of arr2) {
if (item.id === id) {
item.name = obj.name;
break;
}
}
console.timeEnd('⏱');
console.log(arr2);

JavaScript operation array object merge

I have two arrays, and now I want to merge the two arrays.
The first array:
var data = [
{ name: 'aa', value: 1 },
{ name: 'bb', value: 2 },
{ name: 'cc', value: 3 }
];
Two arrays:
var data2 = [
{ name: 'aa' },
{ name: 'bb' },
{ name: 'cc' },
{ name: 'dd' },
{ name: 'ee' }
];
I want to merge them into this:
var data3 = [
{name: 'aa', value: 1},
{name: 'bb', value: 2},
{name: 'cc', value: 3},
{name: 'dd', value: 0},
{name: 'ee', value: 0}
];
console.log(data3)
At present, my experience is not enough. Please help me solve this problem.
Thanks in advance.
You can try following based on following assumptions
data2 is a collection of names and expecting its length to be always more than length of data
Order of objects can be different
var data = [
{ name: 'aa', value: 1 },
{ name: 'bb', value: 2 },
{ name: 'cc', value: 3 }
];
var data2 = [
{ name: 'aa' },
{ name: 'bb' },
{ name: 'cc' },
{ name: 'dd' },
{ name: 'ee' }
];
// Iterate over the names array
var data3 = data2.map(({name}) => {
// get the matched object in data corresponding to the name
var match = data.find((obj) => obj.name === name);
// if found, return value else default value to 0
return match ? match : {name, value : 0};
});
console.log(data3);
If the input arrays are indeed in order like that, then a simple .map would suffice:
var data = [
{ name: 'aa', value: 1 },
{ name: 'bb', value: 2 },
{ name: 'cc', value: 3 }
];
var data2 = [
{ name: 'aa' },
{ name: 'bb' },
{ name: 'cc' },
{ name: 'dd' },
{ name: 'ee' }
];
const output = data2.map(({ name }, i) => ({ name, value: data[i] ? data[i].value : 0 }));
console.log(output);
Create an object lookup for each name using array#reduce. Extract all the values using the Object.values() from the object lookup.
const data1 = [ { name: 'aa', value: 1 }, { name: 'bb', value: 2 }, { name: 'cc', value: 3 } ],
data2 = [ { name: 'aa' }, { name: 'bb' }, { name: 'cc' }, { name: 'dd' }, { name: 'ee' } ],
result = Object.values([data1, data2].reduce((r,a) => {
a.forEach(({name, value = 0}) => {
r[name] = name in r ? r[name] : {name, value};
});
return r;
},{}));
console.log(result);
You can array#concat both the arrays and using array#reduce create an object lookup and then get all the values using the Object.values().
const data1 = [ { name: 'aa', value: 1 }, { name: 'bb', value: 2 }, { name: 'cc', value: 3 } ],
data2 = [ { name: 'aa' }, { name: 'bb' }, { name: 'cc' }, { name: 'dd' }, { name: 'ee' } ],
result = Object.values(data1.concat(data2).reduce((r,{name, value=0}) => {
r[name] = name in r ? r[name] : {name, value};
return r;
},{}));
console.log(result);
var data = [
{ name: 'aa', value: 1 },
{ name: 'bb', value: 2 },
{ name: 'cc', value: 3 }
];
var data2 = [
{ name: 'aa' },
{ name: 'bb' },
{ name: 'cc' },
{ name: 'dd' },
{ name: 'ee' }
];
let output = new Array(data2.length).fill(data2.length).map(v => new Object());
// Logic
data.forEach((val2)=> {
data2.forEach((val, i)=> {
if (val.name == val2.name){
output[i]["name"] = val.name
output[i]["value"] = val2.value
} else{
output[i]["name"] = val.name
}
})
})
output.map((val,i) => {
if (!val.hasOwnProperty("value")){
console.log(val)
val["value"] = 0
}
})
console.log("------Your Expected Format", output)

Transform the data

I have the following data structure:
const data = [
{
name: 'ABC',
salesData: [
{
timestamp: '2017-09-01',
value: 10
},
{
timestamp: '2017-09-02',
value: 2
}
]
},
{
name: 'DEF',
salesData: [
{
timestamp: '2017-09-01',
value: 8
},
{
timestamp: '2017-09-02',
value: 3
}
]
}
];
I would like to transform this to:
[
{
name: 'ABC',
'2017-09-01': 10,
'2017-09-02': 2
},
{
name: 'CDE',
'2017-09-01': 8,
'2017-09-02': 3
}
]
I'm trying to use Underscore's Chain and Map which I'm getting confused. So far I have the following, not sure how do I write the convertedSalesData to transform as per the need:
_.map(data, function(item) {
let name = item.name;
let salesData = item.salesData;
let convertedSalesData = ?
})
With ES6 you can use spread syntax ... to get this result.
const data = [{"name":"ABC","salesData":[{"timestamp":"2017-09-01","value":10},{"timestamp":"2017-09-02","value":2}]},{"name":"DEF","salesData":[{"timestamp":"2017-09-01","value":8},{"timestamp":"2017-09-02","value":3}]}]
var result = data.map(function({name, salesData}) {
return {name, ...Object.assign({}, ...salesData.map(({timestamp, value}) => ({[timestamp]: value})))}
})
console.log(result)
const data = [{
name: 'ABC',
salesData: [{
timestamp: '2017-09-01',
value: 10
},
{
timestamp: '2017-09-02',
value: 2
}
]
},
{
name: 'DEF',
salesData: [{
timestamp: '2017-09-01',
value: 8
},
{
timestamp: '2017-09-02',
value: 3
}
]
}
];
var res = data.map(function(a) {
var obj = {
name: a.name
};
a.salesData.forEach(function(x) {
obj[x.timestamp] = x.value;
})
return obj;
})
console.log(res);
Similar to #Nenad Vracar. I perfer to use 'reduce':
data.map(({ name, salesData }) => ({
name,
...salesData.reduce(
(record, { timestamp, value }) => {
record[timestamp] = value
return record
},
Object.create(null)
)
}))

Categories

Resources