This question already has answers here:
How to get the total depth of an unknown JSON hierarchy?
(2 answers)
Closed 24 days ago.
I have a JSON-like hierarchy of JS objects in the following format:
How can I get object depth? I need count of depth.
Example data:
{
t1: 'V1',
t2: {
head: 'V2',
t3: {
head: 'V3',
t5: 'V5',
t6: 'V6',
},
},
t4: {
head: 'V4',
t7: 'V7',
t8: 'V8',
t9: {
head: 'V9',
t10: 'V10',
t11: 'V11',
t12: {
head: 'V12',
t13: 'V13',
},
},
},
}
I've found this, much cleaner code: https://stackoverflow.com/a/16075976/5214911
The only difference is that I have not one base object but an array of objects as root. How could I simplify the code to spare that extra if and iteration?
Example data:
const data1 = []; // depth: 0
const data2 = [{}, {}, {}]; // depth: 1
const data3 = [{}, // depth: 5
{
"subs": [{
"subs": [{
"subs": [{}]
}, {
"subs": [{
"subs": [{}]
}]
}]
}, {
"subs": [{
"subs": [{}]
}]
}]
},
{}
];
You could map the depth of every children and take the maximum value of it.
const
getDepth = (array = []) =>
1 + Math.max(0, ...array.map(o => getDepth(o.subs))),
test = [{}, { subs: [{ subs: [{ subs: [{}] }, { subs: [{ subs: [{}] }] }] }, {subs: [{ subs: [{}] }] }] }, {}], depth = getDepth(test) - 1; // zero based
console.log(depth);
Related
This question already has answers here:
Javascript nested object traversal
(2 answers)
Closed 1 year ago.
I will like to print [4, 5, 2] as the value of supervisors in the following nested array/objects.
var data = {
supervisors: [
{
0: [
{
id: 4,
name: "Reporter"
}
]
},
{
1: [
{
id: 5,
name: "Officer"
}
]
},
{
2: [
{
id: 2,
name: "Coordinator"
}
]
},
]
};
How can I loop through the data?
let data = {
supervisors: [{
0: [{
id: 4,
name: "Reporter"
}]
},
{
1: [{
id: 5,
name: "Officer"
}]
},
{
2: [{
id: 2,
name: "Coordinator"
}]
},
]
};
let output = []
data.supervisors.forEach(item => {
output.push(item[Object.keys(item)][0].id)
});
console.log(output)
I have a JSON Object with an infinite level of objects inside. I want to frame a JSON Array where it contains the first key in a key and all the associated value in another key.
For eg, The JSON I am having is below,
{
doingnow: {
"action items": { "open": { "child"....}, "In Progress": { "child"....}, "Completed": { "child"....} },
"financial": { "q1": { "jan 2017": { "child"... }, "feb 2017": {....} }, q2: {... }, q3: {... },....}
},
finished: { "discarded": {... } },
.........
}
But the actual JSON Array which I am expecting
[{
key: "doingnow": children: [{
key: "action items", children: [{ key: "open", children: [] }, { key: "In Progress", children: [] }, { key: "Completed", children: [] }],
key: "financial", children: [{ key: q1, children: [{ key: "jan 2017", children: [] }, { key: "feb 2017", children: [] }] },
{ key: q2, children: [{ key: "jan 2017", children: [] }, { key: "feb 2017", children: [] }] }]
}],
}, { key: "finished", children: [{ ...}] }
Can anyone help me with this? Working on it for 2 days. :-(
This a situation where recursion is probably the best choice.
const data = '{doingnow: ... your string ... }'
const jsonObject = JSON.parse(data)
const parseObject = (obj) => {
let returnArray = []
Object.keys(obj).forEach(key => {
let childrens = []
if (typeof obj[key] === 'object' && obj[key] !== null) {
childrens = parseObject(obj[key])
}
returnArray.push({key: key, children: childrens})
})
return returnArray
}
const result = parseObject(jsonObject)
NB. this should work fine for most object, but you may need some more optimization for huge json objects
There is an object and an array.
list: [
{
oldData: {
title: 'abc',
id: 1,
date: '1982-09-30',
budget: 250000,
},
newData: [
{
key: 1,
data: null,
value: 5,
},
{
key: 2,
data: null,
value: 22,
},
...
],
},
{
oldData: {
title: 'blablablaaaaa',
id: 2,
date: '2012-02-23',
budget: 350000,
},
newData: [
{
key: 1,
data: null,
value: 35,
},
{
key: 2,
data: null,
value: 41,
},
...
],
},
... some more datas...
]
as above, There is more data of the same type.
I need to use oldData and newData together, so I want to combine the two.
How can I combine oldData and newData so that there are multiple sets of oldData and newData pairs?
for example, [{ combineData: {...} }, { combineData: {...} }, ... }] here.
I know how to combine array and array, object and object, but I do not know how to do that.
Is there any good solution?
Your desired result is unclear, but you did say you wanted old/new pairs. This answer is different than the others in that it produces an array of combined data objects made of old/new pairs, where the oldData values are duplicated in order to appear alongside each corresponding newData value within its list item.
your original data after the first question update:
let list = [
{
oldData: { title: 'abc', id: 1, date: '1982-09-30', budget: 250000 },
newData: [
{ key: 1, data: null, value: 5 },
{ key: 2, data: null, value: 22 },
//...
],
},
{
oldData: { title: 'blablablaaaaa', id: 2, date: '2012-02-23', budget: 350000 },
newData: [
{ key: 1, data: null, value: 35 },
{ key: 2, data: null, value: 41 },
//...
],
},
//... some more datas...
];
This code maps each {old,new[]} list item into arrays of pairs [{old,new}, {old,new}, ...] that are combined in the final reduce() call:
var combinedDatas = list
.map(listItem => listItem.newData.map(newItem => ({
oldData: listItem.oldData,
newData: newItem
})))
.reduce();
console.log(JSON.stringify(oldNewCombos, null, 4));
produces a list of denormalized pairs:
[
{ list[0].oldData, list[0].newData[0] },
{ list[0].oldData, list[0].newData[1] },
//...rest of list[0] oldData with newData[n] combos
{ list[1].oldData, list[1].newData[0] },
{ list[1].oldData, list[1].newData[1] },
//...rest of list[1] oldData with newData[n] combos
{ list[2].oldData, list[2].newData[0] },
{ list[2].oldData, list[2].newData[1] },
//...rest of list[2] oldData with newData[n] combos
//...
]
You can use map() on the array. And use Object.assign() and spread operator to combine all the properties of all the elements in newData into one object.
const arr = [
{
oldData: {
a:10,
b:20
},
newData: [
{
c:30,
d:40
},
{
e:50,
f:60
}
],
}
]
const res = arr.map(x => ({combinedData:{...x.oldData, ...Object.assign({}, ...x.newData)}}))
console.log(res)
You can map over the array and use object destructuring (...object) to create a new, combined object:
const data = [
{
oldData: {
foo: 'lorem',
},
newData: {
bar: 'ipsum',
},
},
{
oldData: {
foo: 'dolor',
},
newData: {
bar: 'sit amet',
},
},
];
const combined = data.map(record => ({...record.oldData, ...record.newData}));
console.log(combined);
This will overwrite duplicate keys however, so something like:
{
oldData: {
message: 'a',
},
newData: {
message: 'b',
},
}
will become:
{
message: 'b',
}
We have some JSON data where each parent array object can have a property that is an array of "children" along the lines of the following :
data: [
{
value: 1,
parent_id: null,
label: "1.0 - TT One",
children: [
{
value: 3,
label: "1.1 - TT One-One",
parent_id: 1,
},
{
value: 4,
label: "1.2 - TT One-Two",
parent_id: 1,
}
]
},
{
value: 2,
parent_id: null,
label: "2.0 - TT Two",
children: [
{
value: 5,
label: "2.1 - TT Two-One",
parent_id: 2,
}
]
}
]
We'd like to "flatten" the children so that we end up with one array that is all the parents and children as follows (it does not have to stay named data if not efficient):
data: [
{
value: 1,
parent_id: null,
label: "1.0 - TT One"
},
{ <-- FORMER CHILD
value: 3,
label: "1.1 - TT One-One",
parent_id: 1
},
{ <-- FORMER CHILD
value: 4,
label: "1.2 - TT One-Two",
parent_id: 1,
},
{
value: 2,
parent_id: null,
label: "2.0 - TT Two"
},
{ <-- FORMER CHILD
value: 5,
label: "2.1 - TT Two-One",
parent_id: 2,
}
]
Thoughts on how best to accomplish this in an efficient manor? We have underscore if that will help.
Found a buttload of array to array flatten and some object to array flattens, but nothing combining the two. If we had this, we wouldn't have needed to post. If it's not obvious from exactly what we have to exactly what we need, what is the point?
the point is to understand what is your data structure and how to visit every element of that data structure.
Since there are only 2 levels you do not even need to find a general solution to transform your initial data into an array. Do you know how to traverse an array? then you know how to traverse an element that has an array as property as well.
Anyway here is both a recursive and a non recursive generalized solution.
var d = [{
value: 1,
parent_id: null,
label: "1.0 - TT One",
children: [{
value: 3,
label: "1.1 - TT One-One",
parent_id: 1,
},
{
value: 4,
label: "1.2 - TT One-Two",
parent_id: 1,
}
]
},
{
value: 2,
parent_id: null,
label: "2.0 - TT Two",
children: [{
value: 5,
label: "2.1 - TT Two-One",
parent_id: 2,
}]
}
];
function walkRecursive(data) {
let result = []
data.forEach(element => {
let e = { ...element}
result.push(e);
if (e.children) {
let children = walkRecursive(e.children)
result = result.concat(children)
delete e.children
}
});
return result;
}
function walk(data) {
data = data.slice()
let result = []
let d, oldData;
while (d = data.shift()) {
let el = { ...d}
result.push(el)
if (el.children) {
oldData = data
data = el.children.slice();
delete el.children;
} else {
if (oldData && data.length == 0) {
data = oldData
oldData = null;
}
}
}
return result;
}
console.log(walkRecursive(d))
console.log(walk(d))
https://codeburst.io/learn-and-understand-recursion-in-javascript-b588218e87ea
I have attempted googling this question and have searched through stackoverflow but with no success so as a last resort I'm asking just in case anyone can point me in the right direction.
I have put an example of what my code would look like below.
var objectInfo = [
{
name:"object1",
materials: [{
name: "wood",
quantity:10
}, {
name: "stone",
quantity:16
}],
}, {
name:"object2",
materials: [{
name: "wood",
quantity:10
}, {
name: "stone",
quantity:16
}, {
name: "bricks",
quantity:100
}],
}]
My question is, how would I get the length of my materials object array?
My attempt to achieve this was as follows:
function getMaterialsArrayLength(objName) {
for (i = 0; i < objectInfo.length; i++) {
if (objectInfo[i].name == objName) {
return objectInfo[i].materials.length
}
}
};
However the error returned is "cannot read property materials of undefined". Does anyone have any potential solutions to finding the array length?
I apologise if this has been posted before.
var objectInfo = [{
name: "object1",
materials: [{
name: "wood",
quantity: 10
}, {
name: "stone",
quantity: 16
}],
}, {
name: "object2",
materials: [{
name: "wood",
quantity: 10
}, {
name: "stone",
quantity: 16
}, {
name: "bricks",
quantity: 100
}],
}]
function getMaterialsLength(objName) {
return objectInfo.find(o => o.name === objName).materials.length;
}
console.log(getMaterialsLength('object2'));
Might want to add some error checking.
You cannot get the length of an array that does not exist; more precisely, the element of the array you looking at is undefined, so has no material to find the length of:
Just access the object by its index:
var objectInfo = [
{
name:"object1",
materials: [{
name: "wood",
quantity:10
}, {
name: "stone",
quantity:16
}],
}, {
name:"object2",
materials: [{
name: "wood",
quantity:10
}, {
name: "stone",
quantity:16
}, {
name: "bricks",
quantity:100
}],
}];
console.log("objectInfo[0].materials.length: " + objectInfo[0].materials.length);
console.log("objectInfo[1].materials.length: " + objectInfo[1].materials.length);
Using lodash.js.
var objectInfo = [
{
name:"object1",
materials: [{
name: "wood",
quantity:10
}, {
name: "stone",
quantity:16
}],
}, {
name:"object2",
materials: [{
name: "wood",
quantity:10
}, {
name: "stone",
quantity:16
}, {
name: "bricks",
quantity:100
}],
}];
function getMaterialsLength(objName) {
_.each(objectInfo, function(obj) {
if (obj.name == objName) {
console.log(_.size(obj.materials));
}
});
}
getMaterialsLength('object2');
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.2.1/lodash.min.js"></script>