Related
I have an array of objects as below
let arr = [
{
name: "string 1",
details: [
{
id: 1,
values: [
{ date: "12-Mar", score: "15" },
{ date: "13-Mar", score: "16" },
{ date: "14-Mar", score: "17" },
{ date: "15-Mar", score: "18" },
],
},
],
},
{
name: "string 2",
details: [
{
id: 2,
values: [
{ date: "12-Mar", score: "16" },
{ date: "13-Mar", score: "17" },
{ date: "14-Mar", score: "18" },
{ date: "15-Mar", score: "19" },
],
},
],
},
{
name: "string 3",
details: [
{
id: 2,
values: [
{ date: "12-Mar", score: "21" },
{ date: "13-Mar", score: "22" },
{ date: "14-Mar", score: "23" },
{ date: "15-Mar", score: "24" },
],
},
],
},
];
I also have the same data as an object of objects as below
let obj = {
"string 1": {
details: [
{
id: 1,
values: [
{ date: "12-Mar", score: "15" },
{ date: "13-Mar", score: "16" },
{ date: "14-Mar", score: "17" },
{ date: "15-Mar", score: "18" },
],
},
],
},
"string 2": {
details: [
{
id: 2,
values: [
{ date: "12-Mar", score: "16" },
{ date: "13-Mar", score: "17" },
{ date: "14-Mar", score: "18" },
{ date: "15-Mar", score: "19" },
],
},
],
},
"string 3": {
details: [
{
id: "2",
values: [
{ date: "12-Mar", score: "21" },
{ date: "13-Mar", score: "22" },
{ date: "14-Mar", score: "23" },
{ date: "15-Mar", score: "24" },
],
},
],
},
};
I want to find all the dates & all the scores as an array.
For the array of ojects, with the help of answer here (How to find all values of a specific key in an array of nested objects?), I was able to get the result with the code below.
Since I did not want the dates to be repeated, I created a Set
dates = new Set(getValue(arr, "date"))
However, for the object of objects, I am not able to get the results. How do I go about it.
Also, I have the option to get my data as an array of objects or an object of objects. Since I have to perform a lot of manipulation/analysis (I will be using this with D3 library t build charts), which is the better format? Can anyone guide? Thanks.
You could use a recursive approach (as in the referenced answer) to pick all properties for a given key. One can also add a unique parameter, if this is set to true we'll create a Set from the properties to ensure we don't return any duplicates:
let arr = [ { name: "string 1", details: [ { id: 1, values: [ { date: "12-Mar", score: "15" }, { date: "13-Mar", score: "16" }, { date: "14-Mar", score: "17" }, { date: "15-Mar", score: "18" }, ], }, ], }, { name: "string 2", details: [ { id: 2, values: [ { date: "12-Mar", score: "16" }, { date: "13-Mar", score: "17" }, { date: "14-Mar", score: "18" }, { date: "15-Mar", score: "19" }, ], }, ], }, { name: "string 3", details: [ { id: 2, values: [ { date: "12-Mar", score: "21" }, { date: "13-Mar", score: "22" }, { date: "14-Mar", score: "23" }, { date: "15-Mar", score: "24" }, ], }, ], }, ];
let obj = { "string 1": { details: [ { id: 1, values: [ { date: "12-Mar", score: "15" }, { date: "13-Mar", score: "16" }, { date: "14-Mar", score: "17" }, { date: "15-Mar", score: "18" }, ], }, ], }, "string 2": { details: [ { id: 2, values: [ { date: "12-Mar", score: "16" }, { date: "13-Mar", score: "17" }, { date: "14-Mar", score: "18" }, { date: "15-Mar", score: "19" }, ], }, ], }, "string 3": { details: [ { id: "2", values: [ { date: "12-Mar", score: "21" }, { date: "13-Mar", score: "22" }, { date: "14-Mar", score: "23" }, { date: "15-Mar", score: "24" }, ], }, ], }, };
function getProperties(obj, key, unique = true, result = []) {
for(let k in obj) {
if (typeof(obj[k]) === 'object') {
getProperties(obj[k], key, unique, result);
} else if (k === key) {
result.push(obj[k]);
}
}
return unique ? [...new Set(result)]: result;
}
console.log('Dates (arr):', JSON.stringify(getProperties(arr, 'date', true)))
console.log('Scores (arr):', JSON.stringify(getProperties(arr, 'score', true)))
console.log('Dates (obj):', JSON.stringify(getProperties(obj, 'date', true)))
console.log('Scores (obj):', JSON.stringify(getProperties(obj, 'score', true)))
You can iterate over the top-level keys in your object like this:
for (let key in obj){
let val = obj[key]
/* From here you can proceed with finding all values
like you did with the array
*/
}
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);
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);
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);
So I have 4 jsons with that looks like this:
{
"group": "A",
"id": "50"
"person": [
{
"name": 'Joe',
"age": '29'
},
{
"name": 'Jessie',
"age": '27'
}
]
}
I used this function to create an array with all the people from 4 different json's files.
list.forEach(list => {
list.person.forEach(person => {
peopleArray.push(person);
});
})
The problem is, when I pick a position from that array, I want to be able to access the group and the ID as well for example:
console.log(peopleArray[1].group);
Is that possible? Or I would have to those values inside the person?
Just include those values in the person object
const data = {
group: "A",
id: "50",
person: [
{
name: 'Joe',
age: '29'
},
{
name: 'Jessie',
age: '27'
}
]
}
data.person.map(obj => ({...obj, group: data.group, groupId: data.id}))
The result is:
[
{
age: "29",
group: "A",
groupId: "50",
name: "Joe"
},
{
age: "27",
group: "A",
groupId: "50",
name: "Jessie"
}
]