Mapping Nested JSON - javascript

I try to mapping nested JSON in React JS.
My JSON data like this,
"beautifuldata": [
{ "id":"1", "name":"a"},
{ "id":"2", "name":"b"},
{ "id":"3", "name":"c"},
{ "id":"4", "name":"d"},
{ "id":"5", "name":"e"},
{ "id":"6", "name":"f"},
{ "id":"7", "name":"g"}]
this data came from an API. And I can write my data to the console. But everything went wrong when I try to access the inner side. For example, I want to get id from my JSON data,
I try this
[beautifuldata].map(x => console.log(x));
this code line gave all data,
[beautifuldata].map(x => console.log(x.id));
this code line gave me undefined. I want to access all data inside my JSON. What am I missing?

You are returning the whatever console.log(x.id) returns which is undefined;
You need to return the x.id
let obj = {
beautifuldata: [
{ id: "1", name: "a" },
{ id: "2", name: "b" },
{ id: "3", name: "c" },
{ id: "4", name: "d" },
{ id: "5", name: "e" },
{ id: "6", name: "f" },
{ id: "7", name: "g" },
],
};
const result = obj.beautifuldata.map((x) => x.id);
console.log(result);

remove [ ] from this line
[beautifuldata].map(x => console.log(x.id));
To read
beautifuldata.map(x => console.log(x.id));
EDIT
If you want to access data outside the map function,
beautifuldata.map(x => {
/* Work with x properties here*/
console.log(x.id)
return x
}
// thanks to #mhodges

I suggest a solution like below might be an appropriate approach.
var rst = {
"beautifuldata": [
{ "id":"1", "name":"a"},
{ "id":"2", "name":"b"},
{ "id":"3", "name":"c"},
{ "id":"4", "name":"d"},
{ "id":"5", "name":"e"},
{ "id":"6", "name":"f"},
{ "id":"7", "name":"g"}]
}
rst.beautifuldata.map(i => console.log(i.id));
/* -- or --- */
rst.beautifuldata.forEach(i => console.log(i.id));
Hope that helps or gives you a hint.

Related

Javascript Lodash replace array with another [duplicate]

This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 10 months ago.
I'm trying to manipulate an array like this:
data = [
{
"id":"1",
"items":[
{
"title":"item 1"
},
{
"title":"item 2"
}
]
},
{
"id":"2",
"items":[
{
"title":"item2 1"
},
{
"title":"item2 2"
}
]
}
]
I need, for example, to push another array:
[
{
"title":"item new 1"
},
{
"title":"item new 2"
}
]
inside data[0].items and obtain:
data = [
{
"id":"1",
"items":[
{
"title":"item new 1"
},
{
"title":"item new 2"
}
]
},
{
"id":"2",
"items":[
{
"title":"item2 1"
},
{
"title":"item2 2"
}
]
}
]
...how can I do this maintaining immutability, for example with Lodash?
Not understand anding how to change only a specific sub object in a data structure.
Somebody have suggestions?
Thanks
Presented below is one possible way to immutably add given array into a particular index "items" prop.
Code Snippet
const immutableAdd = (aIdx, addThis, orig) => {
const newData = structuredClone(orig);
newData[aIdx].items = addThis;
return newData;
};
const data = [{
"id": "1",
"items": [{
"title": "item 1"
},
{
"title": "item 2"
}
]
},
{
"id": "2",
"items": [{
"title": "item2 1"
},
{
"title": "item2 2"
}
]
}
];
const addThisArr = [{
"title": "item new 1"
},
{
"title": "item new 2"
}
];
console.log('immutableAdd result: ', immutableAdd(0, addThisArr, data));
console.log('original data: ', data);
.as-console-wrapper { max-height: 100% !important; top: 0 }
Explanation
Use structuredClone() to deep-clone existing data array
Navigate to the aIdx of the cloned-array
Assign the given array (to be added) into aIdx's items prop
NOTE
This solution does not use lodash as it is not mandatory (to use lodash) to perform immutable operations.
If you want to maintain the immutability of original data, just map the content of original data to the new data as you want, and wrap your logic into a pure function to improve readability.
const dataOriginal = [{
"id": "1",
"items": [{
"title": "item 1"
},
{
"title": "item 2"
}
]
},
{
"id": "2",
"items": [{
"title": "item2 1"
},
{
"title": "item2 2"
}
]
}
]
const dataNew = createDataWithSomethingNew(dataOriginal, [{
"title": "item new 1"
},
{
"title": "item new 2"
}
])
function createDataWithSomethingNew(data, props) {
return data.map(function changeItemsOfId1ToProps(value) {
if (value.id === '1') {
return {
id: value.id,
items: props
}
} else {
return value
}
})
}
lodash has a method _.update can modify object with the correct path in string provided.
Another method _.cloneDeep can copy you object deeply. So that change in the pre-copied object will not affect the cloned object.
Finally use a deep freeze function to call Object.freeze recursively on the cloned object to make it immutable.
var data = [
{
"id":"1",
"items":[
{
"title":"item 1"
},
{
"title":"item 2"
}
]
},
{
"id":"2",
"items":[
{
"title":"item2 1"
},
{
"title":"item2 2"
}
]
}
]
var clonedData = _.cloneDeep(data) // copy the full object to avoid modify the source data
// update the data of that path '[0].items' in clonedData
_.update(clonedData, '[0].items', function(n) {
return [
{
"title":"item new 1"
},
{
"title":"item new 2"
}
]
})
// provide object immutability
const deepFreeze = (obj1) => {
_.keys(obj1).forEach((property) => {
if (
typeof obj1[property] === "object" &&
!Object.isFrozen(obj1[property])
)
deepFreeze(obj1[property])
});
Object.freeze(obj1)
};
deepFreeze(clonedData)
data[2] = {id: 3} // data will be changed
data[1].items[2] = {title: "3"} // and also this one
clonedData[2] = {id: 3} // nothing will be changed
clonedData[1].items[2] = {title: "3"} // and also this one
console.log(`data:`, data);
console.log(`clonedData:`, clonedData);
Runkit Example

loop from nested object javascript

I have a javascript object which has the nested array called interaction, now what I wanted to do is a loop from each object of the main array and fetch the values from the interaction array, I'm a kind of a newbie with iteration and looping. here below is the object
var data = [{
'id':'1',
'boothid':[{'id':'1','name':'yyy'}],
'interaction':[{
'userid':'1',
'username':'user1',
},{
'userid':'2',
'username':'user2',
}]
},
{
'id':'2',
'boothid':[{'id':'2','name':'xxx'}],
'interaction':[{
'userid':'4',
'username':'user4',
},
{
'userid':'5',
'username':'user5',
},
{
'userid':'6',
'username':'user6',
}],
'resource':'2',
},
{
'id':'3',
'boothid':[{'id':'2','name':'zzz'}],
'interaction':[{
'userid':'4',
'username':'user4',
}],
'resource':'3',
}]
console.log(data);
expected output
yyy
{
"userid": "1",
"username": "user1"
}
{
"userid": "2",
"username": "user2"
}
xxx
{
"userid": "4",
"username": "user4"
}
{
"userid": "5",
"username": "user5"
}
{
"userid": "6",
"username": "user6"
}
zzz
{
"userid": "4",
"username": "user4"
}
here what I'm trying to achieve is, I want to loop from the data object and show that in the frontend, so basically the output will be in 3 tables with respected booth names ex: table1= xxx, table2=yyy, table3=zzz, and the users in a particular booth will be displayed at td of theirs table.
You can use a .map. I made some assumptions:
At the time of writing the expected output has non-unique properties in single objects in the "itarations" array. Maybe you intended to have that object split into separate objects, each with its own "username" property.
"itarations" is a non-existent word. Maybe you meant "interactions".
In the example, the boothid array has always one entry. I'll assume this is always the case.
The code:
let data = [{id:'1',boothid:[{id:'1',name:'yyy'}],interaction:[{userid:'1',username:'user1',},{userid:'2',username:'user2',}]},{id:'2',boothid:[{id:'2',name:'xxx'}],interaction:[{userid:'4',username:'user4',},{userid:'5',username:'user5',},{userid:'6',username:'user6',}],resource:'2',},{id:'3',boothid:[{id:'2',name:'zzz'}],interaction:[{userid:'4',username:'user4',}],resource:'3',}];
let result = data.map(o => ({
boothname: o.boothid[0].name,
interactions: o.interaction.map(({username}) => ({ username }))
}));
console.log(result);
I suggest you to use the map function.
var data = [
{
'id':'1',
'boothid':[{'id':'1','name':'yyy'}],
'interaction':[
{'userid':'1', 'username':'user1'},
{'userid':'2', 'username':'user2'}
]
},
{
'id':'2',
'boothid':[{'id':'2','name':'xxx'}],
'interaction':[
{'userid':'4', 'username':'user4'},
{'userid':'5', 'username':'user5'},
{'userid':'6', 'username':'user6'}
]
}
];
var result = data.map(({boothid, interaction}) => ({
boothname: boothid[0].name,
interaction
}));
console.log(result);
You can try this.
var data = [
{
'id':'1',
'boothid':[{'id':'1','name':'yyy'}],
'interaction':[{
'userid':'1',
'username':'user1',
},{
'userid':'2',
'username':'user2',
}]
},
{
'id':'2',
'boothid':[{'id':'2','name':'xxx'}],
'interaction':[{
'userid':'4',
'username':'user4',
},
{
'userid':'5',
'username':'user5',
},
{
'userid':'6',
'username':'user6',
}],
'resource':'2',
},
{
'id':'3',
'boothid':[{'id':'2','name':'zzz'}],
'interaction':[{
'userid':'4',
'username':'user4',
}],
'resource':'3',
}];
var result = data.map(({boothid, interaction}) => ({
boothname: boothid[0].name,
interaction: interaction.map(({username}) => username)
}));
console.log(result);
friends thank you for your response and ideas, as andy mentioned link the above comment helped me to get the required answer. here below is my answer
var data = [{
'id':'1',
'boothid':[{'id':'1','name':'yyy'}],
'interaction':[{
'userid':'1',
'username':'user1',
},{
'userid':'2',
'username':'user2',
}]
},
{
'id':'2',
'boothid':[{'id':'2','name':'xxx'}],
'interaction':[{
'userid':'4',
'username':'user4',
},
{
'userid':'5',
'username':'user5',
},
{
'userid':'6',
'username':'user6',
}],
'resource':'2',
},
{
'id':'3',
'boothid':[{'id':'2','name':'zzz'}],
'interaction':[{
'userid':'4',
'username':'user4',
}],
'resource':'3',
}]
for (let i of data){
console.log(i.boothid[0].name);
for(let j of i.interaction ){
console.log(j);
}
}
let interactions = [];
data.map(obj => {
interactions.push({
boothname: obj.boothid[0].name,
interactions: obj.interaction,
})
})
You can loop over "data" array with map it will give you each element on iteration where you can pick boothname from "obj.boothid" and interactions from "obj.interaction".

how to make nested array objects in javascript in a key value pair format

array data=[
{
"id":1,
"name":"john",
"income":22000,
"expenses":15000
},
{
"id":2,
"name":"kiran",
"income":27000,
"expenses":13000
},
{
"id":1,
"name":"john",
"income":35000,
"expenses":24000
}
]
i want to make a new array set in following format which is in a key value pair. ie result set.
can you please explain the best method. ? how to achive using foreach.?
tried using foreach method by looping each element. but cant get the desired output format
var result= [ {
"name": "john",
"series": [
{
"name": "income",
"value": 22000
},
{
"name": "expenses",
"value": 15000
},
]
},
{
"name": "kiran",
"series": [
{
"name": "income",
"value": 27000
},
{
"name": "expenses",
"value": 13000
},
]
}]
// Your array
const result = [
{
name: "john",
series: [
{
name: "income",
value: 22000,
},
{
name: "expenses",
value: 15000,
},
],
},
{
name: "kiran",
series: [
{
name: "income",
value: 27000,
},
{
name: "expenses",
value: 13000,
},
],
},
];
// What is .map function?
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
// Output
// map return a new function.
// it's a loop method but more equipped
result.map((item, index) => {
const seriesKeyValues = {};
// forEach is too, it's a loop method.
// but not have a return value,
// just loops and give you item on each loop
item.series.forEach(serie => {
//seriesKeyValues is a object.
// different between seriesKeyValues.serie.name
// it's a bracket notation
// look this documentation
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#computed_property_names
seriesKeyValues[serie.name] = serie.value;
});
// return new Object
// ... is 'spread syntax' basically combine objects
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#spread_properties
// spread syntax is a new way.
// old way is https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
return {
id: index,
name: item.name,
...seriesKeyValues,
};
});
I hope it will help :). if you don't understand any lines of code, i can explain

How to create a JS object and append it to an array

I have the following data :
const data=
{
"1": [
{
"sales_project_id": 5,
"sales_project_name": "name",
"sales_project_est_rev": "123.00",
"project_status": {
"id": 1,
"label": "Start",
"description": null
}
},
{
"sales_project_id": 6,
"sales_project_name": "name2",
"sales_project_est_rev": "123.00",
"project_status": {
"id": 1,
"label": "Start",
"description": null
}
}
],
"2": [],
"4": []
}
These data are grouped in my backend based on their Status , in this case im only showing 2 status , but they are dynamic and can be anything the user defines.
What i wish to do is to transform the above data into the format below :
const data =
{
columns: [
{
id: // id of status here,
title: //label of status here,
cards: [
{
id : //sales_project_id here,
title: //sales_project_name here,
},
]
},
{
id: // id of status here,
title: //label of status here,
cards: [
{
id : //sales_project_id here,
title: //sales_project_name here,
},
]
}
]}
My guess would be to iterate over the data , however i am pretty unfamiliar with doing so , would appreciate someone's help!
Here is what i could come up with so far:
const array = []
Object.keys(a).map(function(keyName, keyIndex) {
a[keyName].forEach(element => {
#creating an object of the columns array here
});
})
after some trial and error , manage to accomplish this , however , im not sure if this is a good method to do so.
Object.keys(projects).map(function(keyName, keyIndex) {
// use keyName to get current key's name
// and a[keyName] to get its value
var project_object = {}
project_object['id'] = projects[keyName][0].id
project_object['title'] = projects[keyName][0].label
project_object['description'] = projects[keyName][0].description
console.log( projects[keyName][1])
var card_array = []
projects[keyName][1].forEach(element => {
var card = {}
card["id"] = element.sales_project_id
card["title"] = element.sales_project_name
card["description"] = element.sales_project_est_rev
card_array.push(card)
});
project_object["cards"] = card_array
array.push(project_object)
})
Im basically manipulating some the scope of the variables inorder to achieve this
See my solution, I use Object.keys like you, then I use reduce:
const newData = { columns: Object.keys(data).map((item) => {
return data[item].reduce((acc,rec) => {
if (typeof acc.id === 'undefined'){
acc = { id: rec.project_status.id, title: rec.project_status.label, ...acc }
}
return {...acc, cards: [...acc.cards, { id:rec.sales_project_id, title:rec.sales_project_name}]}
}, {cards:[]})
})}
See full example in playground: https://jscomplete.com/playground/s510194
I'd just do this. Get the values of data using Object.values(data) and then use reduce to accumulate the desired result
const data=
{
"1": [
{
"sales_project_id": 5,
"sales_project_name": "name",
"sales_project_est_rev": "123.00",
"project_status": {
"id": 1,
"label": "Start",
"description": null
}
},
{
"sales_project_id": 6,
"sales_project_name": "name2",
"sales_project_est_rev": "123.00",
"project_status": {
"id": 1,
"label": "Start",
"description": null
}
}
],
"2": [],
"4": []
};
const a = Object.values(data)
let res =a.reduce((acc, elem)=>{
elem.forEach((x)=>{
var obj = {
id : x.project_status.id,
title : x.project_status.label,
cards : [{
id: x.sales_project_id,
title: x.sales_project_name
}]
}
acc.columns.push(obj);
})
return acc
},{columns: []});
console.log(res)

mongo update script: change fields in embedded documents

I am writing a script to update(add and rename) certain fields, which are part of an embedded document within the ones stored in the db collection.
to give an example document:
{
_id: UUID("025bda29-0d09-4923-8f7f-ea2e825be2c8"),
name: "test",
sets: [
{
"name": "1",
"values": [
{
name: "a",
value: 5
}
]
},
{
"name": "2",
"values": [
{
name: "a",
value: 3
}
]
}
]
}
This is my script:
function convertGroup (group) {
for (var i = 0; i < group.sets.length; i++) {
var set = group.sets[i];
var oldValuesField = "sets." + i.toString() + ".values";
var mainValuesField = "sets." + i.toString() + "mainValues";
var additionalValuesField = "sets." + i.toString() + ".additionalValues";
db.getCollection('group').updateOne({
"_id" : group._id
}, {
$set: {
mainValuesField : set.values,
additionalValuesField : [ ]
},
$unset: {
oldValuesField: ""
}
});
}
}
db.getCollection('group').find({'sets.0.mainValues': {$exists: false}}).forEach(convertGroup);
According to the documentation the $rename does not work on arrays, that is why I used set and unset.
what happens when I run this code, is that I get the mainValues field and additionalValues field in the group document, and not in the set documents.
this is what I want it to become:
{
_id: UUID("025bda29-0d09-4923-8f7f-ea2e825be2c8"),
name: "test",
sets: [
{
"name": "1",
"mainValues": [
{
name: "a",
value: 5
}
],
"additionalValues": [ ]
},
{
"name": "2",
"mainValues": [
{
name: "a",
value: 3
}
],
"additionalValues": [ ]
}
]
}
Can anyone explain to me why this happens and how I can make this work the way I want it to?
I managed to fix it by rewriting the script like this:
function convertGroup(group) {
group.sets.forEach(function (set) {
if (!set.mainValues) {
$set : {
set.mainValues = set.values
}
}
if (!set.additionalValues) {
$set : {
set.additionalValues = []
}
}
});
db.getCollection('group').update({'_id': group._id}, group);
}
db.getCollection('group').find({'sets.mainValues': {$exists: false}}).forEach(convertGroup)
the different is mostly not using the notation 'sets.[index].values' but editing it directly on the json and using 'update' instead of 'updateOne'

Categories

Resources