Accessing nodes by ID - javascript

this might be a daft question but...
I'm just jquery to access an object using:
obj["surveySpec"]["3"]["Survey"]["5"]["description"];
the problem is that depending on the results it can be a different length, what does stay the same is the id of 42333
Is there a way to search for that ID and bring back the values?
I tried
var result2 = $.grep(obj2, function(e){ return e.id === 42333; });
but that didn't work
The object is:
Object
Object
id:1
registration:"NA123"
serviceVersion:"V2"
surveySpec:Array[7]
0:Object
1:Object
2:Object
3:Object
Survey:Array[15]
0:Object
1:Object
2:Object
3:Object
4:Object
5:Object
description:"survey results, 5, 2 and 3"
id:42333
items:Array[3]
name:"survey results"
value:"standard"

var test = {
id: 1,
items: [
{
id: 11,
description: "three",
surveys: [
{
id: 121,
description: "one"
},
{
id: 122,
description: "two"
}
]
},
{
id: 12,
description: "seven"
},
{
id: 13,
description: "four",
surveys: [
{
id: 131,
description: "five"
},
{
id: 132,
description: "six"
}
]
}
]
};
function findById(obj, id) {
if (obj) {
if (obj.id == id)
return obj;
for(var key in obj) {
if ((typeof obj[key]).toLowerCase() != "string" &&
(typeof obj[key]).toLowerCase() != "number") {
var result = findById(obj[key], id);
if (result)
return result;
}
}
}
return null;
}
var result = findById(test, 131);
console.log("result:");
console.log(result);

var myVar = '';
$.each(obj["surveySpec"],function(index,object){
$.each(obj["survey"],function(ind,innerObject){
if(innerOject.id === 42333){
myVar = innerObject.description;
return false;}
});
});
looks like this might be what you are looking for.

Related

How to code 'ID of DOM method to using in recursion'?

I have a problem in 'getObjectById to using in recursion'. Executing the function getObject(data, '11') ---> undefined. I don't know why this happens: undefined.
In function getObject(data, '1'~'9') ---> I got the solved. But '11' ,'12', '13', '14' ---> undefined
For solving this problem, I have to use forEach, Array.prototype.apply, but I cannot solve it.
Using filter ---> TypeError: Cannot read property 'filter' of undefined
Using length ---> TypeError: Cannot read property 'length' of undefined
In first under line, I have got the problem to solve. In second under line, I wrote the code to solve this problem. As I think that I explain my logic to solving the problem. But, in test case, it is failed.
The solution to this problem is:
let output = getObjectById(TREE_DATA.items, '1'))
console.log(output) --> { "id": "1", "name": "johnny" }
--in first under line,
let TREE_DATA = {
items: [
{
id: "1",
name: "johnny"
},
{
id: "2",
name: "ingi",
children: [
{
id: "3",
name: "johnson"
},
{
id: "4",
name: "katy"
},
{
id: "5",
name: "steve",
children: [
{
id: "6",
name: "lisa"
},
{
id: "7",
name: "penny",
children: [
{
id: "8",
name: "john"
},
{
id: "9",
name: "hoyong"
}
]
},
{
id: "10"
}
]
},
{
id: "11"
},
{
id: "12"
}
]
},
{
id: "13"
},
{
id: "14"
}
]
};
--in second under line,
function getObject(json, id) {
let test = json.items;
let newA = [];
function getA(a, id) {
a.filter(function(e) {
console.log("this is : ", e);
if (e.id && e.id === id) {
return newA.push(e);
} else if (e.id !== id && e.children) {
return getA(e.children, id);
}
});
}
getA(test, id);
return newA[0];
}
Because your input data is a recursive structure, a program with a recursive structure will be the best match. In this case you have -
a list of nodes (TREE_DATA.items)
where each node (object) may contain a children property, which is also a list of nodes
This recursive relationship gives us a unique opportunity to learn about special kind of recursion where one function, A, calls function B, which in turn calls function A, which calls B, and so on... this is called mutual recursion.
We start with a function that takes just one of the input nodes, aptly named find1. It accepts a single node, destructured to children and o, and an id to search for, id -
const find1 = ({ children = [], ...o }, id = 0) =>
o.id == id // if the object's id matches the input id,
? o // match found! return the object
: findAll(children, id) // otherwise findAll of the children with the id
Next it's obvious we need to implement findAll. It accepts a list of nodes, destructured to first and more, and an id to search for, id -
const findAll = ([ first, ...more ], id = 0) =>
first === undefined // if the list is empty,
? undefined // there's nothing to search! return no match
: find1(first, id) // find1 the first item in the list using the id
|| findAll(more, id) // OR findAll on more using the same id
That's it! The functions almost writes themselves with no need for extraneous variables or steps. It behaves exactly like we expect -
console.log(findAll(TREE_DATA.items, 1))
// { id: "1", name: "johnny" }
console.log(findAll(TREE_DATA.items, 11))
// { id: "11" }
console.log(findAll(TREE_DATA.items, 99))
// undefined (no match found)
Verify the results in your own browser by running the snippet below -
const find1 = ({ children = [], ...o }, id = 0) =>
o.id == id
? o
: findAll(children, id)
const findAll = ([ first, ...more ], id = 0) =>
first === undefined
? undefined
: find1(first, id) || findAll(more, id)
const TREE_DATA =
{items:[{id:"1",name:"johnny"},{id:"2",name:"ingi",children:[{id:"3",name:"johnson"},{id:"4",name:"katy"},{id:"5",name:"steve",children:[{id:"6",name:"lisa"},{id:"7",name:"penny",children:[{id:"8",name:"john"},{id:"9",name:"hoyong"}]},{id:"10"}]},{id:"11"},{id:"12"}]},{id:"13"},{id:"14"}]}
console.log(findAll(TREE_DATA.items, 1))
// { id: "1", name: "johnny" }
console.log(findAll(TREE_DATA.items, 11))
// { id: "11" }
console.log(findAll(TREE_DATA.items, 99))
// undefined (no match found)
Is this what you are looking for?
let TREE_DATA = {
items: [
{
id: "1",
name: "johnny"
},
{
id: "2",
name: "ingi",
children: [
{
id: "3",
name: "johnson"
},
{
id: "4",
name: "katy"
},
{
id: "5",
name: "steve",
children: [
{
id: "6",
name: "lisa"
},
{
id: "7",
name: "penny",
children: [
{
id: "8",
name: "john"
},
{
id: "9",
name: "hoyong"
}
]
},
{
id: "10"
}
]
},
{
id: "11"
},
{
id: "12"
}
]
},
{
id: "13"
},
{
id: "14"
}
]
};
function getObject(json, id) {
let test = json.items;
let newA = [];
function getA(a, id) {
a &&
a.forEach(function(e) {
if (e.id === id) {
newA.push(e);
} else if (e.children) {
getA(e.children, id);
}
});
}
getA(test, id);
return newA[0];
}
function getObjectById(items, key) {
let ret = {};
for (let item of items) {
if (item.id === key) {
return item;
}
if (item.children) {
let innerRet = getObjectById(item.children, key);
if (Object.keys(innerRet).length) return innerRet;
}
}
return ret;
}
console.log("2", getObjectById(TREE_DATA.items, "2"));
console.log("3", getObjectById(TREE_DATA.items, "3"));
console.log("11", getObjectById(TREE_DATA.items, "11"));
console.log("12", getObjectById(TREE_DATA.items, "12"));
console.log("13", getObjectById(TREE_DATA.items, "13"));
console.log("2", getObject(TREE_DATA, "2"));
console.log("3", getObject(TREE_DATA, "3"));
console.log("11", getObject(TREE_DATA, "11"));
console.log("12", getObject(TREE_DATA, "12"));
console.log("13", getObject(TREE_DATA, "13"));
Edit: debugged and added your function as well.

Traversing through JSON string to inner levels using recursive function using JavaScript

I have a JSON input which can go to any number of levels.
Here is the sample
var testJSON = [
{
'name':'USER1',
'id':1,
'child':[],
},{
'name':'USER2',
'id':2,
'child':[{
'name':'USER2_CHILD1',
'id':21,
'child':[]
},{
'name':'USER2_CHILD2',
'id':22,
'child':[{
'name':'USER2_CHILD2_CHILD1',
'id':221,
'child':[]
}]
}],
},{
'name':'USER3',
'id':3,
'child':[{
'name':'USER3_CHILD1',
'id':31,
'child':[]
}],
}];
I want to add a JSON data in child array by finding matching id using the recursive function. For example, if want to add JSON object at id==1; then it was possible by using for loop but what if I want to add JSON object at id==22 or id==221.
I am trying using below code
var body = '';
function scan(obj)
{
var k;
if (obj instanceof Object) {
for (k in obj){
if (obj.hasOwnProperty(k)){
body += 'scanning property ' + k + '<br/>';
scan( obj[k] );
}
}
} else {
body += 'found value : ' + obj + '<br/>';
};
};
scan(testJSON);
document.getElementById('output').innerHTML = body;
You could use an iteration with a check and return the object, if found.
function getObject(array, id) {
var object;
array.some(o => object = o.id === id && o || getObject(o.child || [], id));
return object;
}
var data = [{ name: "USER1", id: 1, child: [] }, { name: "USER2", id: 2, child: [{ name: "USER2_CHILD1", id: 21, child: [] }, { name: "USER2_CHILD2", id: 22, child: [{ name: "USER2_CHILD2_CHILD1", id: 221, child: [] }] }] }, { name: "USER3", id: 3, child: [{ name: "USER3_CHILD1", id: 31, child: [] }] }];
console.log(getObject(data, 1));
console.log(getObject(data, 21));
console.log(getObject(data, 221));
Try this function, you need to parse JSON before
function insertRecord(id,dataToInsert,jsonInput){
let checkIndex = function (arrayElement){
return arrayElement.id === id;
}
let index = jsonInput.findIndex(checkIndex);
if(index != -1) {
if(jsonInput[index].child) {
jsonInput[index].child.push(dataToInsert);
}
else {
jsonInput[index].child = [dataToInsert];
}
}
else {
jsonInput.forEach(function(arrEle, eleIndex){
if(arrEle.child) {
insertRecord(id,dataToInsert,arrEle.child);
}
});
}
}
insertRecord(22,{
'name':'USER1',
'id':33,
'child':[],
},testJSON);

How to Retrieve a sub-object from an object where the ID of the sub-object is known

I have an object called Suppliers where the id is always unique as follows:
var suppliers = {
Supplier1: {
id: 1,
name: 'Supplier1',
SVGTemplate: 'svg-supplier1'
},
Supplier2: {
id: 2,
name: 'Supplier2',
SVGTemplate: 'svg-supplier2'
},
Supplier3: {
id: 3,
name: 'Supplier3',
SVGTemplate: 'svg-supplier3'
}
}
How can I return the sub-object (e.g return suppliers.Supplier1) when all I know is the id of the sub object? I tried to use .filter, but that only seems to work on arrays:
function findById(source, id) {
return source.filter(function (obj) {
return +obj.id === +id;
})[0];
}
var supplierarray = findById(suppliers, myKnownID);
return supplierarray;
You need to loop over the object using for-in loop, you tried to use .filter which is for array.
So you can change findById definition to below
var suppliers = {
Supplier1: {
id: 1,
name: 'Supplier1',
SVGTemplate: 'svg-supplier1'
},
Supplier2: {
id: 2,
name: 'Supplier2',
SVGTemplate: 'svg-supplier2'
},
Supplier3: {
id: 3,
name: 'Supplier3',
SVGTemplate: 'svg-supplier3'
}
}
// Should return single object not array, as id is unique as OP said
function findById(source, id) {
for(var key in source){
if(source[key].id === id){
return source[key];
}
}
return null;
}
findById(suppliers,3);// {id: 3, name: "Supplier3", SVGTemplate: "svg-supplier3"}
Object.keys(suppliers).map(key => suppliers[key]).find(({id}) => id === someId);
You can search for any key in its child objects.
Object.prototype.findBy = function(propName, propVal){
for( var i in this ){
if( this[i][ propName ] == propVal ){
return this[i];
}
}
return undefined;
};
var suppliers = {
Supplier1: {
id: 1,
name: 'Supplier1',
SVGTemplate: 'svg-supplier1'
},
Supplier2: {
id: 2,
name: 'Supplier2',
SVGTemplate: 'svg-supplier2'
},
Supplier3: {
id: 3,
name: 'Supplier3',
SVGTemplate: 'svg-supplier3'
}
}
console.log(suppliers.findBy("id",1));
Here i've added function inside prototype of root Object.

Recursive search function for Javascript object with arrays of nested objects

I have to create a javascript function to do a recursive search on an object and get the label name for the given ID.
I tried with the below code but it returns undefined for any id. Please help me to fix this issue.
function GetLabel(data, Id) {
var i,
currentChild,
result;
if (Id == data.Id) {
return data['Label'];
} else {
for (field in data) {
if (typeof(data[field]) == "object") {
result = GetLabel(data[field], Id);
if (result != "") return result;
}
if (data[field] == Id) {
result = data['Label'];
return result;
}
}
}
}
This answer is based on the data structure of this question: JSON Schema for tree structure
This proposal uses an a function for recursive call and some changes, basically for the iteration of child, which is an array instead of an object, which may supposed to be.
After a check if child is an array, Array#some helps iterating and stops if the wanted id is found.
I suggest to use a common style guide for naming convention and write all properties in small letters, as well as functions which may not be used as constructor.
function getLabel(data, id) {
var result;
if (id === data.id) {
return data.label;
}
Array.isArray(data.child) && data.child.some(function (a) {
result = getLabel(a, id);
if (result) {
return true;
}
});
return result;
}
var tree = { id: 1, label: "A", child: [{ id: 2, label: "B", child: [{ id: 5, label: "E" }, { id: 6, label: "F" }, { id: 7, label: "G" }] }, { id: 3, label: "C" }, { id: 4, label: "D", child: [{ id: 8, label: "H" }, { id: 9, label: "I" }] }] },
i;
for (i = 1; i < 10; i++) {
document.write(getLabel(tree, i) + '<br>');
}

node.js + Object Array

In my node app i have to construct an object array from another object array.
Consider my object array as..
[ { id_0: 356, id_1: 33, name_1: 'aaaa' },
{ id_0: 756, id_1: 89, name_1: 'bbbbb' },
{ id_0: 456, id_1: 89, name_1: 'ccccc' },
{ id_0: 356, id_1: 27, name_1: 'dddd' } ]
I have to construct an object array as like below:
[{
"356":["33":"aaaa","27":"ddddd"],------------->Changes made
"456":[{"89":"cccc"}],
"756":[{"89":"bbbbbbbb"}]
}]
I tried using async.map.But i cant get the right way to do it.Please help me to solve this.Thanks in advance...
You can use Array.prototype.reduce function, like this
console.log(data.reduce(function(result, current) {
var obj = {};
result[current.id_0] = result[current.id_0] || [];
obj[current.id_1] = current.name_1;
result[current.id_0].push(obj);
return result
}, {}));
Output
{ '356': [ { '33': 'aaaa' }, { '27': 'dddd' } ],
'456': [ { '89': 'ccccc' } ],
'756': [ { '89': 'bbbbb' } ] }
If you want to convert this to an array of object, just wrap the result of data.reduce with [] like this
console.log([data.reduce(function(result, current) {
...
...
}, {})]);
Edit:
result[current.id_0] = result[current.id_0] || [];
this line makes sure that result[current.id_0] is an array. If the value of result[current.id_0] is truthy, then that value is rturned but if it is not, then [] will be returned. So, a new array will be created and assigned to result[current.id_0]. It is actually a shorthand for
if (result.hasOwnProperty(current.id_0) === false) {
result[current.id_0] = [];
}
Edit 2: If you like to keep the grouped elements as an object, you could do like this
console.log(data.reduce(function(result, current) {
result[current.id_0] = result[current.id_0] || {};
result[current.id_0][current.id_1] = current.name_1;
return result
}, {}));
Output
{ '356': { '27': 'dddd', '33': 'aaaa' },
'456': { '89': 'ccccc' },
'756': { '89': 'bbbbb' } }

Categories

Resources