I need to extract json and print it. At first I did manually but that's obviously not the right way. When I try to use forEach loop looped through got 3 object not sure what to do next. My question is is it possible to display data using only loops?
jsonDisplay = () => {
let data = `{
"name": "GI",
"size": 10,
"nodes": [
{
"name": "Mysterious",
"size": 2,
"nodes": [
{
"name": "Center",
"size": 1,
"nodes": [
{
"name": "Fisherman",
"size": 0.5,
"nodes": []
}
]
},
{
"name": "Dog",
"size": 1,
"nodes": []
}
]
},
{
"name": "Cat",
"size": 4,
"nodes": []
}
]
}
`
let json = JSON.parse(data);
let display = document.getElementById('json');
let display2 = document.getElementById('jsonloop');
console.log(json);
json.nodes.forEach(function(element) {
console.log(element);
});
display.innerHTML = `${json.name} ${json.size}
<br>
${json.name} - ${json.nodes[0].name} ${json.nodes[0].size}
<br>
${json.name} - ${json.nodes[0].name} - ${json.nodes[0].nodes[0].name} ${json.nodes[0].nodes[0].size}
<br>
${json.name} - ${json.nodes[0].name} - ${json.nodes[0].nodes[0].name} ${json.nodes[0].nodes[0].nodes[0].name} - ${json.nodes[0].nodes[0].nodes[0].size}
<br>
${json.name} - ${json.nodes[0].name} - ${json.nodes[0].nodes[1].name} - ${json.nodes[0].nodes[1].size}
<br>
${json.name} - ${json.nodes[1].name} - ${json.nodes[1].size}`;
}
jsonDisplay();
So you want to print out the name/size of each nested object? Here's a basic recursive function that will help.
const data = {"name":"GI","size":10,"nodes":[{"name":"Mysterious","size":2,"nodes":[{"name":"Center","size":1,"nodes":[{"name":"Fisherman","size":0.5,"nodes":[]}]},{"name":"Dog","size":1,"nodes":[]}]},{"name":"Cat","size":4,"nodes":[]}]};
(function recursivePrint({ name, size, nodes }) {
console.log(name, size);
nodes.length && nodes.forEach(node => recursivePrint(node));
})(data);
Related
I'm trying to change the structure of a json by removing duplicate keys. Otherwise, to put the children of a same name inside only one name node.
Current JSON:
{
"name": "flare",
"children": [
{
"name": "analytics",
"children": [
{
"name": "cluster",
"children": [
{
"name": "AgglomerativeCluster",
"size": [
"3938"
]
}
]
}
]
},
{
"name": "analytics",
"children": [
{
"name": "cluster",
"children": [
{
"name": "CommunityStructure",
"size": [
"3812"
]
}
]
}
]
}
]
}
Desired output:
{
"name": "flare",
"children": [
{
"name": "analytics",
"children": [
{
"name": "cluster",
"children": [
{
"name": "AgglomerativeCluster",
"size": 3938
},
{
"name": "CommunityStructure",
"size": 3812
}
]
}
]
}
]
};
Thanks for your help.
Typically, StackOverflow isn't the place to have people write code for you, and your question should be more specific as to with what part of your algorithm you are having trouble. However, this looked fun, so I did it.
I solved this by first converting it to an object whose properties are the names and values are the children/size. This insured that each named instance was grouped with other named instances.
var mutate = function(desired, current) {
for (var x = 0; x < current.length; x++) {
if (Object.hasOwnProperty.call(current[x], 'size')) {
desired[current[x].name] = parseInt(current[x].size[0], 10);
}
else {
if (!Object.hasOwnProperty.call(desired, current[x].name)) {
desired[current[x].name] = Object.create(null);
}
mutate(desired[current[x].name], current[x].children);
}
}
return desired;
};
I then converted that back to your original desired format by iterating over the Object.entries (key/value pairs).
var mutate2 = function(current) {
var desired = [];
var entries = Object.entries(current);
for (var x = 0; x < entries.length; x++) {
var o = Object.create(null);
o.name = entries[x][0];
if (typeof entries[x][1] === 'number') {
o.size = entries[x][1];
}
else {
o.children = mutate2(entries[x][1]);
}
desired.push(o);
}
return desired;
};
You get your result by using this hideous beast:
var desiredJson = mutate2(mutate(Object.create(null), [ currentJson ]));
console.log(desiredJson);
I have been trying to delete a nested object from a JavaScript object, with no success and have not been able to find the correct answer through searching previous posts.
Here is what I have been trying to do.
<code id='code'></code>
var myobj = {
"children": [
{
"name": "albuterol ",
"children": [
{
"name": "albuterol - fluticasone ",
"children": [
{
"name": "prednisone ",
"children": [
{
"name": "dexamethasone ",
"children": [],
"size": 1,
"colname": "CONCEPT_NAME.4"
}
],
"size": 3,
"colname": "CONCEPT_NAME.3"
}
],
"size": 4,
"colname": "CONCEPT_NAME.2"
}]}]}
function deleteObject(myobj) {
var x = delete myobj.colname
return (myobj.name, myobj.children)
}
document.getElementById('code').innerText = JSON.stringify(deleteObject(myobj))
I want to delete the object colname. Am I missing something or is the code completely incorrect?
You need a recursive function to delete the property.
var myobj = {
"children": [
{
"name": "albuterol ",
"children": [
{
"name": "albuterol - fluticasone ",
"children": [
{
"name": "prednisone ",
"children": [
{
"name": "dexamethasone ",
"children": [],
"size": 1,
"colname": "CONCEPT_NAME.4"
}
],
"size": 3,
"colname": "CONCEPT_NAME.3"
}
],
"size": 4,
"colname": "CONCEPT_NAME.2"
}]}]}
function deleteColnameRecursive(obj){
delete obj.colname
if(obj.children){
for(var i=0;i<obj.children.length;i++)
deleteColnameRecursive(obj.children[i]);
}
}
deleteColnameRecursive(myobj);
console.log(myobj);
MyObj does not directly have a property of colname.
MyObj has an array named Children.
To delete the proper attribute, select the proper object. For example myObj.children[0].colname
I got a json object like this
{
"id": 1,
"name": "A",
"nodes": [
{
"id": 2,
"name": "B",
"nodes": [
{
"id": 3,
"name": "C",
"nodes": []
}
]
}
]
}
If I have as input the id of the object, lets take id: 3, how would I scan the whole three find the object with specific id and then scan upwards to the last parent.
So after the scan is done I know that C has parent B and B has parent A, so I can then print that like A-B-C
all based on me knowing the id of object I want to find parents of.
The above object can be of any lenght and can have many nodes and levels. So anyone has any idea how to traverse up the levels to top level if starting at specific level?
edit:
when I try to parse this
let data = [
{
"id": 1,
"name": "name",
"testing": "something",
"nodes": [
{
"id": 11,
"name": "name",
"testing": "something",
"nodes": []
}
]
},
{
"id": 2,
"name": "name",
"testing": "something",
"nodes": []
}
]
to json object by doing JSON.parse(data) I get an error
SyntaxError: Unexpected token o in JSON at position 1
at JSON.parse (<anonymous>)
Also tried this
let jsonObject = JSON.stringify($scope.data);
jsonObject = JSON.parse(jsonObject);
createTree(jsonObject, null, nodeData.id)
and get different error:
TypeError: obj.nodes is not iterable
Do a basic DFS scan, add parent property along the way, and climb up when node found.
let jsonParsed = JSON.parse(`
{
"id": 1,
"name": "A",
"nodes": [
{
"id": 2,
"name": "B",
"nodes": [
{
"id": 3,
"name": "C",
"nodes": []
}
]
}
]
}
`)
let arr = []
function climbTree(obj) {
arr.unshift(obj.name)
if (obj.parent) {
climbTree(obj.parent)
}
}
function createTree(obj, parent = null, targetId = null) {
obj.parent = parent
if (targetId === obj.id) {
return climbTree(obj)
}
for (let node of obj.nodes) {
createTree(node, obj, targetId)
}
}
createTree(jsonParsed, null, 3)
console.log(arr.join('-'))
I am building a JSON file dynamically. I want to add a JSON array in the JSON object. The JSON looks like-
{"name":"Root",
"children":[
{"name":"child1"},
{"name":"child2"}
]}
Now, I want to add -
[{"name":"child11"},{"name":"child12"}]
under "child1" object. How to do it? I have also tried keeping blank children object while creating the original JSON object, but JSON parser doesn't keep those empty children block. In current scenario, when I am using push() function to add new child it throws exception. Any help is much appreciated.
Thanks in advance!!
Edit1: I think I didn't made myself clear enough. I have researched SO before posting this question, and I guess this is not a duplicate question. My target JSON is -
{
"name": "Root",
"children": [{
"name": "child1",
"children": [{
{"name": "child11"},
{"name": "child12"}
}]
},
{
"name": "child2",
"children": [{
{"name": "child21"},
{"name": "child22"}
}]
}
]
};
Here is the code snippet that I am trying to run -
flare = {
"name": "Root",
"children": [{
"name": "child1",
"children": [{
{"name": "child11"},
{"name": "child12"}
}]
},
{
"name": "child2",
"children": [{
{"name": "child21"},
{"name": "child22"}
}]
}
]
};
var updatedJson = twoLevelSelection(flare);
function twoLevelSelection(json){
var root = flare.name;
var string_json = '';
string_json = '{"name": "'+root+'","children": [';
flare.children.forEach(
function(d){
string_json = string_json+ '{"name":"'+d.name+'","children":[]},';
}
);
string_json = string_json.substring(0,string_json.length-1);
string_json = string_json + ']}';
return JSON.parse(string_json);
}
// data is the original data.i.e - flare
// d is the clicked node, under which children to be added
function traverse(data,d){
var queue = [];
var next = data;
while(next){
if(next.children){
next.children.forEach(
function(k){
queue.push(k);
}
)
}
if(queue[0].name==d.name){
alert(queue[0].children);
//d.children = queue[0].children;
var child_string='';
var child_array = [];
queue[0].children.forEach(
function(j){
child_string = '{"name": "'+j.name+'"}';
child_array.push(child_string);
}
);
console.log(child_array);
d.children = [...child_array];
console.log(updatedJson);
//update(updatedJson);
break;
}else{
next= queue.shift();
}
}
}
The traverse() will be called on a click event.
Sorry, for not providing clarity at first place. Thanks!
You can use the Spread Operator to accomplish that.
This code snippet has a function called addElements which find the target and adds the new elements to the children array.
var obj = {
"name": "Root",
"children": [{
"name": "child1"
},
{
"name": "child2"
}
]
};
var newArray = [
{ "name": "child11"},
{ "name": "child12"}
];
var addElements = function(target, array) {
obj.children.forEach(function(child) {
if (child.name === target) {
child['children'] = [...(child['children'] || []), ...newArray];
return;
}
});
};
addElements('child1', newArray);
console.log(obj);
See? now your obj.childre[0].children array contains the new elements.
I've been struggling to find/build a recursive function to parse this JSON file and get the total depth of its children.
The file looks something like this:
var input = {
"name": "positive",
"children": [{
"name": "product service",
"children": [{
"name": "price",
"children": [{
"name": "cost",
"size": 8
}]
}, {
"name": "quality",
"children": [{
"name": "messaging",
"size": 4
}]
}]
}, {
"name": "customer service",
"children": [{
"name": "Personnel",
"children": [{
"name": "CEO",
"size": 7
}]
}]
}, {
"name": "product",
"children": [{
"name": "Apple",
"children": [{
"name": "iPhone 4",
"size": 10
}]
}]
}]
}
You can use a recursive function to go through the whole tree:
getDepth = function (obj) {
var depth = 0;
if (obj.children) {
obj.children.forEach(function (d) {
var tmpDepth = getDepth(d)
if (tmpDepth > depth) {
depth = tmpDepth
}
})
}
return 1 + depth
}
The function works as follow:
If the object is not a leaf (i.e the object has the children attribute), then:
Compute the depth of each child, save the maximal one
return 1 + the depth of the deepest child
Otherwise, return 1
jsFiddle: http://jsfiddle.net/chrisJamesC/hFTN8/
EDIT
With modern JavaScript, the function could look like this:
const getDepth = ({ children }) => 1 +
(children ? Math.max(...children.map(getDepth)) : 0)
jsFiddle: http://jsfiddle.net/chrisJamesC/hFTN8/59/
This will count the number of "leaves" in a tree:
var treeCount = function (branch) {
if (!branch.children) {
return 1;
}
return branch.children.reduce(function (c, b) {
return c + treeCount(b);
}, 0)
}
And an alternative way to get depth:
var depthCount = function (branch) {
if (!branch.children) {
return 1;
}
return 1 + d3.max(branch.children.map(depthCount));
}