Add the key value based on property in array object javascript - javascript

I would like to know how to map the key value pair based on property in javascript.
I need to add the title property to obj1 if the name matches.
var obj1 = [
{"item": 1, code: "SG", name: "Engg", status: "A"},
{"item": 2, code: "TH", name: "Civil", status: "C"},
{"item": 1, code: "ML", name: "IT", status: "I"}
]
var obj2 = [
{"name": "Engg", "title": "Service"},
{"name": "Civil", "title": "MRT"}
]
Expected Output
var newobj= [
{"item": 1, code: "SG", name: "Engg", status: "A", title: "Service"},
{"item": 2, code: "TH", name: "Civil", status: "C",title:"MRT"},
{"item": 1, code: "ML", name: "IT", status: "I"}
]

var obj1 = [{
"item": 1,
code: "SG",
name: "Engg",
status: "A"
},
{
"item": 2,
code: "TH",
name: "Civil",
status: "C"
},
{
"item": 1,
code: "ML",
name: "IT",
status: "I"
}
]
var obj2 = [{
"name": "Engg",
"title": "Service"
},
{
"name": "Civil",
"title": "MRT"
}
]
const a = obj1.map(el => ({
...el,
...obj2.find(item => item.name === el.name)
}))
console.log(a)

1) Build titles object from obj2
2) Use reduce method on obj1 and update title from obj2.
var obj1 = [
{ item: 1, code: "SG", name: "Engg", status: "A" },
{ item: 2, code: "TH", name: "Civil", status: "C" },
{ item: 1, code: "ML", name: "IT", status: "I" }
];
var obj2 = [
{ name: "Engg", title: "Service" },
{ name: "Civil", title: "MRT" }
];
const titles = obj2.reduce((acc, { name, title }) => (acc[name] = title, acc), {});
const updated = obj1.map(item => ({
...item,
title: titles[item.name] || ""
}));
console.log(updated);

Related

Filter array object by name

I have array object like this, can you help me?
[{id: 1, name: "contractor"},
{id: 2, name: "owner", },
{id: 3, name: "manager", },
{id: 4, name: "customer", },
{id: 5, name: "admin",}]
I want a format like that:
if admin
[admin:
{id: 1, name: "contractor"},
{id: 2, name: "owner", },
{id: 3, name: "manager", },
{id: 4, name: "customer", }]
if contractor
[contractor:
{id: 2, name: "owner", },
{id: 3, name: "manager", },
{id: 4, name: "customer", }]
if owner
[owner:
{id: 3, name: "manager", },
{id: 4, name: "customer", }]
if manager
[manager:
{id: 4, name: "customer", }]
Based on the comments, i guess you need this
let array = [
{id: 1, name: "contractor"},
{id: 2, name: "owner"},
{id: 3, name: "manager"},
{id: 4, name: "customer"},
{id: 5, name: "admin"}
]
const admin = { admin: array.filter(obj => obj.id < 5) }
const contractor = { contractor: array.filter(obj => [2, 3, 4].includes(obj.id)) }
const owner = { owner: array.filter(obj => [3, 4].includes(obj.id)) }
const manager = { manager: array.filter(obj => obj.id === 4) }
console.log(admin, contractor, owner, manager)
IF you want to make it so it will only generate the array if it is included in the name, then you can use array.reduce
const array = [
{id: 1, name: "contractor"},
{id: 2, name: "owner"},
{id: 3, name: "manager"},
{id: 4, name: "customer"},
{id: 5, name: "admin"}
];
const objects = array.reduce((prev, curr) => {
if (prev[curr.name]) {
return {
...prev,
[prev[curr.name]]: prev[curr.name].concat(curr),
}
}
return {
...prev,
[curr.name]: [curr]
}
}, {});
console.log(objects);
You have to sort the data first, as you can see the below code. I hope this would be helpful. thanks
const array = [
{ id: 1, name: "contractor", sort: 2 },
{ id: 2, name: "owner", sort: 3 },
{ id: 3, name: "manager", sort: 4 },
{ id: 4, name: "customer", sort: 5 },
{ id: 5, name: "admin", sort: 1 }
];
let nameArr = [];
let arr = [];
let newArray = [];
const sortedData = array.sort((a, b) => a.sort - b.sort);
sortedData.forEach(ele => {
array.forEach(item => {
if (item.name !== ele.name) {
if (newArray.length) {
if (!nameArr.includes(item.name) && (item.name !== ele.name)) {
arr.push(item);
}
} else {
arr.push(item);
}
}
})
newArray.push({ [ele.name]: arr });
nameArr.push(ele.name);
arr = []
})
console.log(newArray)
Result will be this:
[
{
"admin": [
{
"id": 1,
"name": "contractor",
"sort": 2
},
{
"id": 2,
"name": "owner",
"sort": 3
},
{
"id": 3,
"name": "manager",
"sort": 4
},
{
"id": 4,
"name": "customer",
"sort": 5
}
]
},
{
"contractor": [
{
"id": 2,
"name": "owner",
"sort": 3
},
{
"id": 3,
"name": "manager",
"sort": 4
},
{
"id": 4,
"name": "customer",
"sort": 5
}
]
},
{
"owner": [
{
"id": 3,
"name": "manager",
"sort": 4
},
{
"id": 4,
"name": "customer",
"sort": 5
}
]
},
{
"manager": [
{
"id": 4,
"name": "customer",
"sort": 5
}
]
},
{
"customer": []
}
]

Compare two arrays of objects, where objects in each array have different properties

I have two result sets like this:
const resultSet1 =
[
{
"id": "1",
"version": "3",
"website": "https://xx/version/3",
"name": Ana,
"lastName": Ana,
},
{
"id": "2",
"version": "3",
"website": "https://xx/version/3",
"name": Ana,
"lastName": Ana,
}
]
const resultSet2 =
[
{
"id": "1",
"version": "2",
"birthday": "24.08.1984",
"place": "Europe",
},
{
"id": "2",
"version": "2",
"birthday": "24.08.1984",
"place": "Europe",
},
{
"id": "1",
"version": "1",
"birthday": "24.08.1984",
"place": "Europe",
},
{
"id": "2",
"version": "3",
"birthday": "24.08.1984",
"place": "Europe",
}
]
I want to compare these two result sets, based on id & version. In my const comparisonSet, I want to have elements from the first result set, whose both id & version are not present in the second result set.
const comparisonSet =
[
{
"id": "1",
"version": "3",
"website": "https://xx/version/3",
"name": Ana,
"lastName": Ana,
}
]
How can I achieve this in Javascript?
Any help would be appreciated. Thank you in advance!
You can use filter to get the desired result.
Overall complexity - O(n * 2)
resultSet1.filter(({ id, version }) =>!resultSet2.find((o) => o.id === id && o.version === version));
const resultSet1 = [{
id: "1",
version: "3",
website: "https://xx/version/3",
name: "Ana",
lastName: "Ana",
},
{
id: "2",
version: "3",
website: "https://xx/version/3",
name: "Ana",
lastName: "Ana",
},
];
const resultSet2 = [{
id: "1",
version: "2",
birthday: "24.08.1984",
place: "Europe",
},
{
id: "2",
version: "2",
birthday: "24.08.1984",
place: "Europe",
},
{
id: "1",
version: "1",
birthday: "24.08.1984",
place: "Europe",
},
{
id: "2",
version: "3",
birthday: "24.08.1984",
place: "Europe",
},
];
const result = resultSet1.filter(
({
id,
version
}) =>
!resultSet2.find((o) => o.id === id && o.version === version)
);
console.log(result);
Though it is not so optimized, so you can also create a dictionary and loop up result in O(1) -
Overall complexity O(n)
const dict = resultSet2.reduce((acc, curr) => {
const { id, version } = curr;
acc[`${id}|${version}`] = curr;
return acc;
}, {});
const result = resultSet1.filter(({ id, version }) => !dict[`${id}|${version}`]);
const resultSet1 = [
{
id: "1",
version: "3",
website: "https://xx/version/3",
name: "Ana",
lastName: "Ana",
},
{
id: "2",
version: "3",
website: "https://xx/version/3",
name: "Ana",
lastName: "Ana",
},
];
const resultSet2 = [
{
id: "1",
version: "2",
birthday: "24.08.1984",
place: "Europe",
},
{
id: "2",
version: "2",
birthday: "24.08.1984",
place: "Europe",
},
{
id: "1",
version: "1",
birthday: "24.08.1984",
place: "Europe",
},
{
id: "2",
version: "3",
birthday: "24.08.1984",
place: "Europe",
},
];
const dict = resultSet2.reduce((acc, curr) => {
const { id, version } = curr;
acc[`${id}|${version}`] = curr;
return acc;
}, {});
const result = resultSet1.filter(({ id, version }) => !dict[`${id}|${version}`]);
console.log(result);
I would iterate through one array while filtering the other.
resultSet1.forEach(res1 => {
const filtered = resultSet2.filter(res2 => res2.id === res1.id && res2.version === res1.version);
//if filtered.length === 0 you can do what you want with res1
});
const Ana = 'Ana';
const resultSet1 = [
{ id: '1', version: '3', website: 'https://xx/version/3', name: Ana, lastName: Ana, },
{ id: '2', version: '3', website: 'https://xx/version/3', name: Ana, lastName: Ana, },
];
const resultSet2 = [
{ id: '1', version: '2', birthday: '24.08.1984', place: 'Europe', },
{ id: '2', version: '2', birthday: '24.08.1984', place: 'Europe', },
{ id: '1', version: '1', birthday: '24.08.1984', place: 'Europe', },
{ id: '2', version: '3', birthday: '24.08.1984', place: 'Europe', },
];
const idAndVersionNotInSecondResultSet = ({ id, version }) =>
resultSet2.every(({ id: i, version: v }) => i !== id || version !== v);
const comparisonSet = resultSet1.filter(idAndVersionNotInSecondResultSet);
console.log(comparisonSet);

Update object value in array with values in other array using hashtables or hashmap

I have two arrays Array1 and Array2, i am updating rate of object in Array1 with rate of same object (With same ID) in Array 2. I have a functions that loops through both arrays to get desired result. After going through some of the answers on Stack overflow I feel Hash table is best suited to reduce the complexity. I was just curious to understand how same can be implemented using the has maps.
let Array1 = [{
id: 1,
name: "IceCream",
details: [{
id: "12",
name: "milk",
quantity: "50",
rate: "100"
},
{
id: "13",
name: "cream",
quantity: "50",
rate: "300"
}
]
},
{
id: 2,
name: "Coffee",
details: [{
id: "14",
name: "Coffee bean",
quantity: "60",
rate: "200"
},
{
id: "15",
name: "water",
quantity: "60",
rate: "300"
}
]
},
{
id: 3,
name: "Tea",
details: [{
id: "16",
name: "Tea leaf",
quantity: "50",
rate: "700"
}]
}
]
let Array2 = [{
id: 1,
name: "IceCream",
details: [{
id: "12",
name: "milk",
quantity: "50",
rate: "500"
},
{
id: "13",
name: "cream",
quantity: "50",
rate: "700"
}
]
},
{
id: 2,
name: "Coffee",
details: [{
id: "14",
name: "Coffee bean",
quantity: "60",
rate: "800"
},
{
id: "15",
name: "water",
quantity: "60",
rate: "8000"
}
]
}
]
Array1 = Array1.map(item => {
let element = Array2.find(e => e.id == item.id);
if (element) {
item.details = item.details.map(e => {
let detail = element.details.find(d => d.id == e.id);
if (detail)
e.rate = detail.rate;
return e;
});
}
return item;
});
console.log(Array1);
Make a map of Array2's items (by id) and each of Array2's details (by id), and then you can iterate over Array1 and mutate its properties with low complexity:
const items2ById = {};
for (const item of Array2) {
items2ById[item.id] = item;
}
const items2DetailsById = {};
for (const detail of Array2.flatMap(({ details }) => details)) {
items2DetailsById[detail.id] = detail;
}
for (const item of Array1) {
if (!items2ById[item.id]) continue;
for (const detail of item.details) {
if (items2DetailsById[detail.id]) {
detail.rate = items2DetailsById[detail.id].rate;
}
}
}
Note that since you're mutating the existing objects, .map isn't really appropriate, since you don't really care to create a new array - instead, just iterate over the array and mutate it as needed.
let Array1 = [{
id: 1,
name: "IceCream",
details: [{
id: "12",
name: "milk",
quantity: "50",
rate: "100"
},
{
id: "13",
name: "cream",
quantity: "50",
rate: "300"
}
]
},
{
id: 2,
name: "Coffee",
details: [{
id: "14",
name: "Coffee bean",
quantity: "60",
rate: "200"
},
{
id: "15",
name: "water",
quantity: "60",
rate: "300"
}
]
},
{
id: 3,
name: "Tea",
details: [{
id: "16",
name: "Tea leaf",
quantity: "50",
rate: "700"
}]
}
]
let Array2 = [{
id: 1,
name: "IceCream",
details: [{
id: "12",
name: "milk",
quantity: "50",
rate: "500"
},
{
id: "13",
name: "cream",
quantity: "50",
rate: "700"
}
]
},
{
id: 2,
name: "Coffee",
details: [{
id: "14",
name: "Coffee bean",
quantity: "60",
rate: "800"
},
{
id: "15",
name: "water",
quantity: "60",
rate: "8000"
}
]
}
];
const items2ById = {};
for (const item of Array2) {
items2ById[item.id] = item;
}
const items2DetailsById = {};
for (const detail of Array2.flatMap(({ details }) => details)) {
items2DetailsById[detail.id] = detail;
}
for (const item of Array1) {
if (!items2ById[item.id]) continue;
for (const detail of item.details) {
if (items2DetailsById[detail.id]) {
detail.rate = items2DetailsById[detail.id].rate;
}
}
}
console.log(Array1);

Update value of object in array with values in other Array [duplicate]

This question already has answers here:
Update value of object with values in different array
(4 answers)
Closed 2 years ago.
I am trying to reproduce my original problem;
I have two arrays in react state Array 1 is an original array from Database and Array2 is an updated array is state.
Objective is to update only changed rates and not quantity (and other pararmters) back to the Database, hence i need to update the values of rates in object of Array1 with the values of the rates in object 2 for a the objects of Array1 matching with the objects in Array2.
Array1 = [{
id: 1,
name: IceCream,
details: [{ id: "12", name: "milk", quantity: "50", rate: "100" },
{ id: "13", name: "cream", quantity: "50", rate: "300" }]
},
{
id: 2,
name: Coffee,
details: [{ id: "14", name: "Coffee bean", quantity: "60", rate: "200" },
{ id: "15", name: "water", quantity: "60", rate: "300" }]
},
{
id: 3,
name: Tea,
details: [{ id: "16", name: "Tea leaf", quantity: "50", rate: "700" }]
}]
Array2 = [{
id: 1,
name: IceCream,
details: [{ id: "12", name: "milk", quantity: "50", rate: "500" },
{ id: "13", name: "cream", quantity: "50", rate: "700" }]
},
{
id: 2,
name: Coffee,
details: [{ id: "14", name: "Coffee bean", quantity: "60", rate: "800" },
{ id: "15", name: "water", quantity: "60", rate: "8000" }]
}]
You need to iterate over the objects in Array1 using .map, check if it exists in Array2 by id using .find. Then, iterate over the details and update the rate if it also exists in that of the second array:
let Array1 = [
{
id:1,
name: "IceCream",
details:[
{id:"12",name:"milk",quantity:"50",rate:"100"},
{id:"13",name:"cream",quantity:"50",rate:"300"}
]
},
{
id:2,
name:"Coffee",
details:[
{id:"14",name:"Coffee bean",quantity:"60",rate:"200"},
{id:"15",name:"water",quantity:"60",rate:"300"}
]
},
{
id:3,
name:"Tea",
details:[
{id:"16",name:"Tea leaf",quantity:"50",rate:"700"}
]
}
]
let Array2 = [
{
id:1,
name: "IceCream",
details:[
{id:"12",name:"milk",quantity:"50",rate:"500"},
{id:"13",name:"cream",quantity:"50",rate:"700"}
]
},
{
id:2,
name:"Coffee",
details:[
{id:"14",name:"Coffee bean",quantity:"60",rate:"800"},
{id:"15",name:"water",quantity:"60",rate:"8000"}
]
}
]
Array1 = Array1.map(item => {
let element = Array2.find(e => e.id == item.id);
if(element){
item.details = item.details.map(e => {
let detail = element.details.find(d => d.id==e.id);
if(detail)
e.rate = detail.rate;
return e;
});
}
return item;
});
console.log(Array1);

Search for all paths to the value in JavaScript object

I have a complex JavaScript object given below.
An example object:
var object= {
"name": "tfifkhul",
"id": "262761",
"children": [
{
"name": "rthrth",
"id": 0,
"children": [
{
"name": "test",
"id": "262762",
"children": []
}
]
},
{
"name": "rthsrth",
"id": 0,
"children": [
{
"name": "test",
"id": "262762",
"children": []
}
]
},
{
"name": "rthrthhrth",
"id": 0,
"children": [
{
"name": "test",
"id": "262762",
"children": [
{
"name": "rtjrtj",
"id": 0,
"children": [
{
"name": "fwefwefwef",
"id": "262768",
"children": []
}
]
},
{
"name": "hsrtjrtdjrtj",
"id": 0,
"children": [
{
"name": "we4yhesrhy",
"id": "262764",
"children": []
}
]
},
{
"name": "lol",
"id": "262763",
"children": [
{
"name": "fwefwefwef",
"id": "262768",
"children": [
{
"name": "87ok78",
"id": "262765",
"children": [
{
"name": "78o78",
"id": 0,
"children": [
{
"name": "we4yhesrhy",
"id": "262764",
"children": [
{
"name": "test1",
"id": 0,
"children": [
{
"name": "",
"id": "262766",
"children": []
}
]
},
{
"name": "test2",
"id": 0,
"children": [
{
"name": "",
"id": "262766",
"children": []
}
]
}
]
}
]
},
{
"name": "7o78o76o8",
"id": 0,
"children": [
{
"name": "",
"id": "262766",
"children": []
}
]
},
{
"name": "ko",
"id": 0,
"children": [
{
"name": "",
"id": "262767",
"children": []
}
]
}
]
}
]
}
]
}
]
}
]
}
]
};
I need to create a function to search for all matching values for key "id" with given value.
So far I have created one recursive function:
function searchOccurances(theObject, value,path) {
var result = null;
if(theObject instanceof Array) {
for(var i = 0; i < theObject.length; i++) {
result = searchOccurances(theObject[i],value,path+","+i);
}
}
else
{
for(prop in theObject) {
if(prop == 'id') {
if(theObject[prop] == value) {
keyOccurances.push(path);
}
}
if((theObject[prop] instanceof Array) || (theObject[prop] instanceof Object))
{
if((theObject[prop].length!=undefined)&&(theObject[prop].length!=0))
{
result = searchOccurances(theObject[prop],value,path+","+prop);
}
}
}
}
return result;
}
keyOccurances=[];
searchOccurances(object,262762,'');
console.log(keyOccurances);
//Output
[",children,0,children,0", ",children,1,children,0", ",children,2,children,0"] -- correct
keyOccurances=[];
searchOccurances(object,262768,'');
console.log(keyOccurances);
//Output
[",children,1,children,0,children,1,children,0", ",children,1,children,0,children,2,children,0"] --wrong
The function returns array of comma separated paths of matched value but doesn't seems to be getting right results. For the first call with value '262762' gives corrects path list but for value '262768' gives incorrect path list.
Kindly help.
I'd suggest to provide a better test object. Would you really have so many children with 'id = 0' in a real use case? Would you have 2 children with the same ID at all? That makes things pretty hard to debug.
Below is an example function that should work as expected.
function search(object, value) {
var res = [], searchPath;
(searchPath = function(children, path) {
var n, newPath;
for(n in children) {
if(typeof children[n].id !== 'undefined' && parseInt(children[n].id, 10) === value) {
res.push(path);
}
newPath = path.slice();
newPath.push(children[n].id);
searchPath(children[n].children, newPath);
}
})([ object ], []);
return res;
}
console.log(search(object, 262762));
console.log(search(object, 262768));
Output:
[["262761", 0], ["262761", 0], ["262761", 0]]
[["262761", 0, "262762", 0], ["262761", 0, "262762", "262763"]]
The above code is not (yet) bullet-proof but hopefully is it short enough to be easily understandable.
If I understand your questions correctly, you're looking for all paths where a specific id is present. I'd recommend not reinventing the wheel here and using an existing library. We use object-scan for most of our data processing now. It's powerful once you wrap your head around it. Here is how you'd answer your question
// const objectScan = require('object-scan');
const findKeys = (haystack, id) => objectScan(['**'], {
joined: true,
filterFn: ({ value }) => value.id === id
})(haystack);
const object = { name: 'tfifkhul', id: '262761', children: [{ name: 'rthrth', id: 0, children: [{ name: 'test', id: '262762', children: [] }] }, { name: 'rthsrth', id: 0, children: [{ name: 'test', id: '262762', children: [] }] }, { name: 'rthrthhrth', id: 0, children: [{ name: 'test', id: '262762', children: [{ name: 'rtjrtj', id: 0, children: [{ name: 'fwefwefwef', id: '262768', children: [] }] }, { name: 'hsrtjrtdjrtj', id: 0, children: [{ name: 'we4yhesrhy', id: '262764', children: [] }] }, { name: 'lol', id: '262763', children: [{ name: 'fwefwefwef', id: '262768', children: [{ name: '87ok78', id: '262765', children: [{ name: '78o78', id: 0, children: [{ name: 'we4yhesrhy', id: '262764', children: [{ name: 'test1', id: 0, children: [{ name: '', id: '262766', children: [] }] }, { name: 'test2', id: 0, children: [{ name: '', id: '262766', children: [] }] }] }] }, { name: '7o78o76o8', id: 0, children: [{ name: '', id: '262766', children: [] }] }, { name: 'ko', id: 0, children: [{ name: '', id: '262767', children: [] }] }] }] }] }] }] }] };
console.log(findKeys(object, '262762'));
/* =>
[ 'children[2].children[0]',
'children[1].children[0]',
'children[0].children[0]' ]
*/
console.log(findKeys(object, '262768'));
/* =>
[ 'children[2].children[0].children[2].children[0]',
'children[2].children[0].children[0].children[0]' ]
*/
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#13.8.0"></script>
Disclaimer: I'm the author of object-scan
Edit: The accepted answer didn't make much sense to me (based on the question), but here is how you could generate the same output
// const objectScan = require('object-scan');
const findIdPath = (haystack, id) => objectScan(['**'], {
reverse: false,
filterFn: ({ value, parents, context }) => {
if (value.id === id) {
context.push(parents.filter((p) => 'id' in p).map((p) => p.id).reverse());
}
}
})(haystack, []);
const object = { name: 'tfifkhul', id: '262761', children: [{ name: 'rthrth', id: 0, children: [{ name: 'test', id: '262762', children: [] }] }, { name: 'rthsrth', id: 0, children: [{ name: 'test', id: '262762', children: [] }] }, { name: 'rthrthhrth', id: 0, children: [{ name: 'test', id: '262762', children: [{ name: 'rtjrtj', id: 0, children: [{ name: 'fwefwefwef', id: '262768', children: [] }] }, { name: 'hsrtjrtdjrtj', id: 0, children: [{ name: 'we4yhesrhy', id: '262764', children: [] }] }, { name: 'lol', id: '262763', children: [{ name: 'fwefwefwef', id: '262768', children: [{ name: '87ok78', id: '262765', children: [{ name: '78o78', id: 0, children: [{ name: 'we4yhesrhy', id: '262764', children: [{ name: 'test1', id: 0, children: [{ name: '', id: '262766', children: [] }] }, { name: 'test2', id: 0, children: [{ name: '', id: '262766', children: [] }] }] }] }, { name: '7o78o76o8', id: 0, children: [{ name: '', id: '262766', children: [] }] }, { name: 'ko', id: 0, children: [{ name: '', id: '262767', children: [] }] }] }] }] }] }] }] };
console.log(findIdPath(object, '262762'));
// => [ [ '262761', 0 ], [ '262761', 0 ], [ '262761', 0 ] ]
console.log(findIdPath(object, '262768'));
// => [ [ '262761', 0, '262762', 0 ], [ '262761', 0, '262762', '262763' ] ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#13.8.0"></script>
Disclaimer: I'm the author of object-scan

Categories

Resources