Reformatting hierarchical JSON data - javascript

I have the following hierarchical JSON data retrieved from a PostgreSQL DB using PHP:
[{"treelevel":"1","app":"Front","lrflag":null,"ic":null,"price":null,"parentlevel":"0","seq":"27", "indexlistid":439755},
{"treelevel":"2","app":"V-Series","lrflag":null,"ic":null,"price":null,"parentlevel":"1","seq":"28", "indexlistid":439755},
{"treelevel":"3","app":"opt J56","lrflag":null,"ic":null,"price":null,"parentlevel":"2","seq":"29", "indexlistid":439755},
{"treelevel":"4","app":"R.","lrflag":"R","ic":"536-01132AR","price":"693.00","parentlevel":"3","seq":"30", "indexlistid":439755},
{"treelevel":"4","app":"L.","lrflag":"L","ic":"536-01133AL","price":"693.00","parentlevel":"3","seq":"31", "indexlistid":439755},
{"treelevel":"3","app":"opt J63","lrflag":null,"ic":null,"price":null,"parentlevel":"2","seq":"32", "indexlistid":439755},
{"treelevel":"4","app":"R.","lrflag":"R","ic":"536-01130R","price":null,"parentlevel":"3","seq":"33", "indexlistid":439755},
{"treelevel":"4","app":"L.","lrflag":"L","ic":"536-01131L","price":null,"parentlevel":"3","seq":"34", "indexlistid":439755}]
I need some way to reformat the data to this:
[{"app": "Front-V-Series-opt J56-R. R", "price": "$693", "ic": "536-01132AR"},
{"app": "Front-V-Series-opt J56-L. L", "price": "$693", "ic": "536-01132AL"},
{"app": "Front-V-Series-opt J63-R. R", "price": null, "ic": "536-01130R"},
{"app": "Front-V-Series-opt J63-L. L", "price": null, "ic": "536-01131L"}]
The parentlevel and treelevel are the 2 keys that make up the tree relationship.
The app value in the new format is a concatenation of the app and lrflag values from all the
nodes in one tree level + the price and ic from the deepest leaf node in the level. This is the
data visualized as a tree:
[
{
"app": "Front",
"children": [
{
"app": "V-Series",
"children": [
{
"app": "opt J56",
"children": [
{
"app": "R. ,
"lrflag": "R",
"ic": "536-01132AR",
"price": "$693"
},
{
"app": "L. ,
"lrflag": "L",
"ic": "536-01132AL",
"price": "$693"
}
]
},
{
"app": "opt J63",
"children": [
{
"app": "R. ,
"lrflag": "R",
"ic": "536-01130R"
},
{
"app": "L. ,
"lrflag": "L",
"ic": "536-01131L"
}
]
}
]
}
]
}
]
I've tried several different ways to do this but am just stuck. Here are some of the functions
that I've attempted to modify and use to no luck. I can't even get the tree correctly built from
these.
function buildTree(list) {
var map = {}, node, roots = [], i;
for (i = 0; i < list.length; i += 1) {
map[list[i].treelevel] = i; // initialize the map
list[i].children = []; // initialize the children
}
for (i = 0; i < list.length; i += 1) {
node = list[i];
if (node.parentlevel !== "0") {
// if you have dangling branches check that map[node.parentId] exists
list[map[node.parentlevel]].children.push(node);
} else {
roots.push(node);
}
}
return roots;
}
function listToTree(data, options) {
options = options || {};
var ID_KEY = options.idKey || 'treelevel';
var PARENT_KEY = options.parentKey || 'parentlevel';
var CHILDREN_KEY = options.childrenKey || 'children';
var tree = [],
childrenOf = {};
var item, id, parentId;
for (var i = 0, length = data.length; i < length; i++) {
item = data[i];
id = item[ID_KEY];
parentId = item[PARENT_KEY] || 0;
// every item may have children
childrenOf[id] = childrenOf[id] || [];
// init its children
item[CHILDREN_KEY] = childrenOf[id];
if (parentId != 0) {
// init its parent's children object
childrenOf[parentId] = childrenOf[parentId] || [];
// push it into its parent's children object
childrenOf[parentId].push(item);
} else {
tree.push(item);
}
};
return tree;
}
unflattenToObject = function(array, parent) {
var tree = {};
parent = typeof parent !== 'undefined' ? parent : {id: 0};
var childrenArray = array.filter(function(child) {
return child.treelevel == parent.parentlevel;
});
if (childrenArray.length > 0) {
var childrenObject = {};
// Transform children into a hash/object keyed on token
childrenArray.forEach(function(child) {
childrenObject[child.treelevel] = child;
});
if (parent.treelevel == 0) {
tree = childrenObject;
} else {
parent['children'] = childrenObject;
}
childrenArray.forEach(function(child) {
unflattenToObject(array, child);
})
}
return tree;
};

the idea is to get the first element's index in the max depth treelevel : 4 then start from there and loop backwards, making sure you don't go through the parents twice, and concatenate what you need along the way, once you reach the top level, you delete that element
wrap that in a function and call it recursively until there's no treelevel : 4 left
var data = [{
"treelevel": "1",
"app": "Front",
"lrflag": null,
"ic": null,
"price": null,
"parentlevel": "0",
"seq": "27",
"indexlistid": 439755
},
{
"treelevel": "2",
"app": "V-Series",
"lrflag": null,
"ic": null,
"price": null,
"parentlevel": "1",
"seq": "28",
"indexlistid": 439755
},
{
"treelevel": "3",
"app": "opt J56",
"lrflag": null,
"ic": null,
"price": null,
"parentlevel": "2",
"seq": "29",
"indexlistid": 439755
},
{
"treelevel": "4",
"app": "R.",
"lrflag": "R",
"ic": "536-01132AR",
"price": "693.00",
"parentlevel": "3",
"seq": "30",
"indexlistid": 439755
},
{
"treelevel": "4",
"app": "L.",
"lrflag": "L",
"ic": "536-01133AL",
"price": "693.00",
"parentlevel": "3",
"seq": "31",
"indexlistid": 439755
},
{
"treelevel": "3",
"app": "opt J63",
"lrflag": null,
"ic": null,
"price": null,
"parentlevel": "2",
"seq": "32",
"indexlistid": 439755
},
{
"treelevel": "4",
"app": "R.",
"lrflag": "R",
"ic": "536-01130R",
"price": null,
"parentlevel": "3",
"seq": "33",
"indexlistid": 439755
},
{
"treelevel": "4",
"app": "L.",
"lrflag": "L",
"ic": "536-01131L",
"price": null,
"parentlevel": "3",
"seq": "34",
"indexlistid": 439755
}
];
// first go look for the max depth in the tree, if it's always four, skip this part and put var max = 4
var max = 0;
data.forEach(function(elem) {
if (elem.treelevel >= max)
max = elem.treelevel;
});
// implement a function to get the index of the first matched element with treelevel = max depth
function getIndex() {
return data.indexOf(data.find((elem) => {
return elem.treelevel == max;
}));
}
var myTree = [];
function formObject(ndx) {
var myObj = {};
myObj.app = [];
var nextTreeLevel = 3;
// start looping from the index of the element in max depth backwards
for (var i = ndx; i >= 0; i--) {
// if the next element ( backwards ) is a parent , this is to avoid going through parent's siblings
if (nextTreeLevel == data[i].parentlevel) {
if (data[i].ic != null) myObj.ic = data[i].ic;
if (data[i].price != null) myObj.price = data[i].price;
if (data[i].lrflag != null) myObj.app.push(data[i].lrflag);
myObj.app.push(data[i].app);
nextTreeLevel = data[i].parentlevel - 1; // prent's level
}
}
data.splice(ndx, 1); // remove the lement once you're done with it
// glue the "app" together, would be better to use array.join but it's not the same join everywhere
myObj.app = myObj.app[4] + '-' + myObj.app[3] + '-' + myObj.app[2] + '-' + myObj.app[1] + ' ' + myObj.app[0];
// just to fill the price with null if there is none
if (myObj.price == undefined) myObj.price = null;
// push the object to the result's array
myTree.push(myObj);
// get the index of the next element in max depth ( 4 )
var nextIndex = getIndex();
// if there's still another element in the max depth, recall the same function with it's index
if (nextIndex > -1)
formObject(nextIndex)
}
formObject(getIndex())
console.log(myTree);

Related

Reorder json in js

I am building a tree, and the order I want is name, desc, then children.
So the json I got is in different order. How do you reorder it or is there a better way to write this code, taking consideration of multiple branches, and may be extra element can be add to the input?
So here is my code:
var arry = [{
"name": "J",
"target": "L",
"desc": "2"
},
{
"name": "L",
"target": "A",
"desc": "1"
},
{
"name": "S",
"target": "L",
"desc": "3"
}
];
function toJSON(data) {
var root = data.find(function(x) {
return !data.some(function(y) {
return y.name === x.target
});
}).target;
console.log(root)
var desc = data.find(function(x) {
return !data.some(function(y) {
return y.name === x.target
});
}).desc;
var b = data.reduce(function(acc, x) {
acc[x.target] = acc[x.target] || [];
acc[x.target].push(x.name);
return acc;
}, {});
var tree = buildTree(root, b);
function buildTree(name, branches, desc) {
var tree = {
'name': name
};
if (branches[name]) {
tree.children = branches[name].map(function(x) {
return buildTree(x, branches, desc)
});
for (var child in branches[name]) {
var x = arry.find(function(i) {
return (i.name === branches[name][child] && i.target === name)
})
tree.children[child].desc = x.desc
}
}
return tree;
}
if (tree.name === root) {
tree.desc = root
}
for (var i in tree) {
console.log(i)
}
return tree;
} // JavaScript name code
var a = toJSON(arry)
console.log(JSON.stringify(a, null, 2))
The result I got is:
{
"name": "A",
"children": [
{
"name": "L",
"children": [
{
"name": "J",
"desc": "2"
},
{
"name": "S",
"desc": "3"
}
],
"desc": "1"
}
],
"desc": "A"
}
The result I want is:
{
"name": "A",
"desc": "A",
"children": [
{
"name": "L",
"desc": "1",
"children": [
{
"name": "J",
"desc": "2"
},
{
"name": "S",
"desc": "3"
}
]
}
]
}
I agree with the question "Why does order matter"
But if you really want...
When creating object literals the keys/properties remain in the order in which they are/were defined (unless the keys are integers, then they will be in numerical order). On the line where you create your tree node you define an object but only put the name property on it. You then add children, then finally set the desc property. If you instead define your object right away they will have that order and you can later mutate the values however you want.
const tree = {
name,
desc: undefined,
children: undefined,
};
var arry = [
{
name: "J",
target: "L",
desc: "2"
},
{
name: "L",
target: "A",
desc: "1"
},
{
name: "S",
target: "L",
desc: "3"
}
];
function toJSON(data) {
var root = data.find(function(x) {
return !data.some(function(y) {
return y.name === x.target;
});
}).target;
console.log(root);
var desc = data.find(function(x) {
return !data.some(function(y) {
return y.name === x.target;
});
}).desc;
var b = data.reduce(function(acc, x) {
acc[x.target] = acc[x.target] || [];
acc[x.target].push(x.name);
return acc;
}, {});
var tree = buildTree(root, b);
function buildTree(name, branches, desc) {
// define your tree node shape here
var tree = {
name,
desc: undefined,
children: undefined
};
if (branches[name]) {
tree.children = branches[name].map(function(x) {
return buildTree(x, branches, desc);
});
for (var child in branches[name]) {
var x = arry.find(function(i) {
return i.name === branches[name][child] && i.target === name;
});
tree.children[child].desc = x.desc;
}
}
return tree;
}
if (tree.name === root) {
tree.desc = root;
}
for (var i in tree) {
console.log(i);
}
return tree;
} // JavaScript name code
var a = toJSON(arry);
console.log(JSON.stringify(a, null, 2));

Create Hashmap like implementation using java-script for json

I am looking to create hashmap like array which will contain key and value derived from another array which has nested objects.
so i am trying the following code.
var testhash={},data=[
{
"yang_type": "container",
"name": "c1",
"value": "",
"children": [
{
"yang_type": "container",
"name": "c2",
"value": "",
"children": [
{
"yang_type": "list",
"name": "Car",
"value": "",
"children": [
{
"yang_type": "leaf",
"name": "wheels",
"value": "",
"children": [
{
"name": "max-elements",
"value": "4",
"children": [],
"yang_type": ""
}
]
}
]
},
{
"yang_type": "",
"name": "text",
"value": "4",
"children": []
}
]
}
]
}
];
var k='';
function loop1(a, depth) {
var l,s='';
if(depth){s += '/';}
k=k+a.yang_type+a.name+a.value;
v=Array(depth + 1).join(s) + a.yang_type+a.name+a.value;
testhash.push(k:v);
//console.log(l);
//console.log(Array(depth + 1).join("/") + a.yang_type,a.name,a.value);
//hashServiceParams.push(Array(depth + 1).join("/") + a.yang_type,a.name,a.value);
Array.isArray(a.children) && a.children.forEach(function(child) {
loop1(child, depth + 1);
});
}
console.log(testhash);
The output, I am expecting is
{"containerc1":*,"containerc2":"containerc1/containerc2","listcar":"containerc1/containerc2/listcar","leafwheels":"containerc1/containerc2/listcar/leafwheels","max-elements":"containerc1/containerc2/listcar/leafwheels/max-elements","text4":"containerc1/text4"}
The above array will act as an hash map that contains key and value , where value stores the part of that data in the tree structure.
my code just calculates the depth and adds / to each level it moves down but i expect the output to be as shown above. Any recommendation coders ?
The following should do the trick (use either version according to your needs):
ECMAScript 6:
function parseData(data, prefix) {
let result = {};
data.forEach(o => {
const key = `${o.yang_type}${o.name}`;
result[key] = prefix ? `${prefix}/${key}` : '*';
if (o.children) {
const newPrefix = prefix ? `${prefix}/${key}` : key;
result = Object.assign(result, parseData(o.children, newPrefix));
}
});
return result;
}
ECMAScript 5:
function shallowMerge(obj1,obj2){
var obj3 = {};
for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
return obj3;
}
function parseData(data, prefix) {
var result = {};
data.forEach(function (o) {
var key = '' + o.yang_type + o.name;
result[key] = prefix ? prefix + '/' + key : '*';
if (o.children) {
var newPrefix = prefix ? prefix + '/' + key : key;
result = shallowMerge(result, parseData(o.children, newPrefix));
}
});
return result;
}
In order to use it you simply need to do the following:
let testhash = parseData(data);
This will populate the testHash with the result you need.

JSON Object get length

I have nested JSON which is as following:
var data = [
{
"id":"4",
"name":"2nd anniversary",
"date":"2015-12-17",
"location":"Mumbai",
"story_body":"Gzjjs jdk djks jdks jdkd jx djdb djd JD djbd djdj d",
"short_link":"izWfs",
"created_at":"2015-12-11 03:49:52",
"path":[
"\/SupportData\/ImpalzB2B\/uploads\/711453354154623.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/90294930451449759544217.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/471453355023537.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/90294930451449759544223.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/90294930451449759544179.jpg"
],
"update_type":"3"
},
{
"id":"7",
"name":"#1styearAnniversary",
"date":"2016-01-20",
"location":"Mumbai",
"story_body":"Bsjsj jdkdk djdkdk dkdkf kdkf dkfj fjfj fjfkjdd djkd",
"short_link":"FHXh0",
"created_at":"2016-01-20 23:10:54",
"path":"\/SupportData\/ImpalzB2B\/uploads\/11453356652175.jpg",
"update_type":"3"
},
{
"id":"19",
"name":"Product qetyfvhchv",
"description":"Cheers Vgdhvjd hugging",
"short_link":"jPE7G",
"created_at":"2016-01-18 05:03:46",
"path":"\/SupportData\/ImpalzB2B\/uploads\/90294930451453118625255.jpg",
"update_type":"4"
},
{
"id":"20",
"name":"F frfgcgj ggvvhv",
"description":" Vdhsj fgjjchk",
"short_link":"hMn8K",
"created_at":"2016-01-18 05:04:16",
"path":"\/SupportData\/ImpalzB2B\/uploads\/90294930451453118654785.jpg",
"update_type":"4"
},
{
"id":"25",
"name":"Gshsh djdj djdkd dkkd",
"description":"Bsjjd djjd djdirj dudir",
"short_link":"dhT6l",
"created_at":"2016-01-22 05:39:31",
"path":[
"\/SupportData\/ImpalzB2B\/uploads\/11453466369930.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369891.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369942.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369934.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369939.jpg"
],
"update_type":"4"
},
{
"id":"26",
"name":"For Healthy Breakfast, head over to our new restaurant in Andheri",
"description":"Delightful upma",
"short_link":"CG0i4",
"created_at":"2016-02-04 06:58:17",
"path":"\/SupportData\/ImpalzB2B\/uploads\/11454594295456.jpg",
"update_type":"4"
},
{
"id":"1",
"body":"#Awesome2Eat",
"votes":"28",
"update_type":"7",
"short_link":"GcKAe",
"created_at":"2016-02-04 01:28:53",
"name":"nehil"
},
{
"id":"10",
"body":"#Bouncy",
"votes":"1",
"update_type":"7",
"short_link":"JXUxz",
"created_at":"2016-02-04 00:12:52",
"name":"nehil"
},
{
"id":"11",
"body":"#Superman",
"votes":"0",
"update_type":"7",
"short_link":"4Keyd",
"created_at":"2016-02-04 01:17:36",
"name":"nehil"
}
]
How do I get lenght of path array from Object?
I tried which gives wrong length.
for (var key in data) {
if(data[key].update_type == '3'){
console.log(data[key].path.length); // 5 and 49 . It Should be 5 and 1
}
};
Also Is this the right way to get each element of Object? :
for (var key in data) {
console.log(data[key].id);
$.each(data[key].path, function (i, obj) {
console.log(obj);
});
};
Fiddle link: http://jsfiddle.net/Nehil/2ym3ffo0/
Because the type of value of data[key].path is not array (second instance), it is a String. And String also has the length attribute which gives the length of string.
make it
for (var key in data) {
if(data[key].update_type == '3')
{
if (typeof data[key].path == "string" )
{
console.log( 1 );
}
else
{
console.log(data[key].path.length); // 5 and 49 . It Should be 5 and 1
//to print all the elements on the console one by one
if ( data[key].path && data[key].path.length > 0 )
{
data[key].path.forEach( function(value){
console.log( value );
} );
}
}
}
}
You can use forEach loop:
The forEach() method executes a provided function once per array
element.
var data = [{
"id": "4",
"name": "2nd anniversary",
"date": "2015-12-17",
"location": "Mumbai",
"story_body": "Gzjjs jdk djks jdks jdkd jx djdb djd JD djbd djdj d",
"short_link": "izWfs",
"created_at": "2015-12-11 03:49:52",
"path": [
"\/SupportData\/ImpalzB2B\/uploads\/711453354154623.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/90294930451449759544217.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/471453355023537.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/90294930451449759544223.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/90294930451449759544179.jpg"
],
"update_type": "3"
}, {
"id": "7",
"name": "#1styearAnniversary",
"date": "2016-01-20",
"location": "Mumbai",
"story_body": "Bsjsj jdkdk djdkdk dkdkf kdkf dkfj fjfj fjfkjdd djkd",
"short_link": "FHXh0",
"created_at": "2016-01-20 23:10:54",
"path": "\/SupportData\/ImpalzB2B\/uploads\/11453356652175.jpg",
"update_type": "3"
}, {
"id": "19",
"name": "Product qetyfvhchv",
"description": "Cheers Vgdhvjd hugging",
"short_link": "jPE7G",
"created_at": "2016-01-18 05:03:46",
"path": "\/SupportData\/ImpalzB2B\/uploads\/90294930451453118625255.jpg",
"update_type": "4"
}, {
"id": "20",
"name": "F frfgcgj ggvvhv",
"description": " Vdhsj fgjjchk",
"short_link": "hMn8K",
"created_at": "2016-01-18 05:04:16",
"path": "\/SupportData\/ImpalzB2B\/uploads\/90294930451453118654785.jpg",
"update_type": "4"
}, {
"id": "25",
"name": "Gshsh djdj djdkd dkkd",
"description": "Bsjjd djjd djdirj dudir",
"short_link": "dhT6l",
"created_at": "2016-01-22 05:39:31",
"path": [
"\/SupportData\/ImpalzB2B\/uploads\/11453466369930.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369891.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369942.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369934.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369939.jpg"
],
"update_type": "4"
}, {
"id": "26",
"name": "For Healthy Breakfast, head over to our new restaurant in Andheri",
"description": "Delightful upma",
"short_link": "CG0i4",
"created_at": "2016-02-04 06:58:17",
"path": "\/SupportData\/ImpalzB2B\/uploads\/11454594295456.jpg",
"update_type": "4"
}, {
"id": "1",
"body": "#Awesome2Eat",
"votes": "28",
"update_type": "7",
"short_link": "GcKAe",
"created_at": "2016-02-04 01:28:53",
"name": "nehil"
}, {
"id": "10",
"body": "#Bouncy",
"votes": "1",
"update_type": "7",
"short_link": "JXUxz",
"created_at": "2016-02-04 00:12:52",
"name": "nehil"
}, {
"id": "11",
"body": "#Superman",
"votes": "0",
"update_type": "7",
"short_link": "4Keyd",
"created_at": "2016-02-04 01:17:36",
"name": "nehil"
}]
data.forEach((a) => { /*ES6 Arrow funtion. can use simple 'function(){}' too*/
if (typeof a.path == "string") {
console.log(1);
} else if(typeof a.path!=='undefined') {
console.log(a.path.length);
}else{
console.log(-1);
}
})
repeatedly throughout this answer I use this code:
var path = (item.path && typeof item.path == 'string' ? [item.path] : item.path) || [];
breaking it down, if item.path is truthy, if it's a string, set it to [item.path] (i.e. an array with a single element == item.path), othewise use item.path
if this results in a falsey value (item.path is undefined or null etc) set path = [] an empty array
Now path will always be an array, so .length/.forEach/$.each will work without any issue (except if item.path is something other that string/array/undefined/null of course)
as you already use jquery.each, you could do this
$.each(data, function(i, item) {
if (item.update_type == '3') {
var path = (item.path && typeof item.path == 'string' ? [item.path] : item.path) || [];
console.log(path.length);
}
});
and
$.each(data, function(i, item) {
console.log(item.id);
var path = (item.path && typeof item.path == 'string' ? [item.path] : item.path) || [];
$.each(path, function (i, obj) {
console.log(obj);
});
});
I prefer to use jquery as little as possible
data.forEach(function (item) {
if (item.update_type == '3') {
var path = (item.path && typeof item.path == 'string' ? [item.path] : item.path) || [];
console.log(path.length);
}
});
and
data.forEach(function (item) {
console.log(item.id);
var path = (item.path && typeof item.path == 'string' ? [item.path] : item.path) || [];
path.forEach(function (obj) {
console.log(obj);
});
});
to use forEach you may need this polyfill if you think you may need to support IE8 or less
This is my solution using UnderscoreJs:
_.each(data, function(item) {
if (item['update_type'] != '3') return;
var path = (_.isString(item.path) ? [item.path] : item.path) || [];
var pathCount = path.length;
// Log path count for item.
pathCount && console.log(pathCount);
// Or log path list for item.
pathCount && _.each(path, function(pathStr) { console.log(pathStr); });
});

filter result using 2 JSON

This is my saved localstorage,
[{"industry_Id":1,"merchant_id":2}]
I want to filter below result, to get HP.
{
"industries": [
{
"id": 1,
"name": "oil and gas",
"merchant": [
{
"id": 1,
"name": "ABC",
},
{
"id": 2,
"name": "DEF",
},
{
"id": 3,
"name": "GHJ",
}
]
},
{
"id": 2,
"name": "IT",
"merchant": [
{
"id": 1,
"name": "Apple",
},
{
"id": 2,
"name": "HP",
},
{
"id": 3,
"name": "Google",
}
]
}
]
}
I thought of using multiple $.each but it have to iterate few times and it's quite redundant.
I would prefer using Javascript for loop, that way you can skip iterating over every object once required element is found.
Without jQuery (using for)
var i, j, merchant = null;
for(i = 0; i < data['industries'].length; i++){
if(data['industries'][i]['id'] == arg[0]['industry_Id']){
for(j = 0; j < data['industries'][i]['merchant'].length; j++){
if(data['industries'][i]['merchant'][j]['id'] == arg[0]['merchant_id']){
merchant = data['industries'][i]['merchant'][j];
break;
}
}
if(merchant !== null){ break; }
}
}
With jQuery (using $.each)
var merchant_found = null;
$.each(data['industries'], function(i, industry){
if(industry['id'] == arg[0]['industry_Id']){
$.each(industry['merchant'], function(i, merchant){
if(merchant['id'] == arg[0]['merchant_id']){
merchant_found = merchant;
}
return (!merchant_found);
});
}
return (!merchant_found);
});
var arg = [{"industry_Id":1,"merchant_id":2}];
var data = {
"industries": [
{
"id": 1,
"name": "oil and gas",
"merchant": [
{
"id": 1,
"name": "ABC",
},
{
"id": 2,
"name": "DEF",
},
{
"id": 3,
"name": "GHJ",
}
]
},
{
"id": 2,
"name": "IT",
"merchant": [
{
"id": 1,
"name": "Apple",
},
{
"id": 2,
"name": "HP",
},
{
"id": 3,
"name": "Google",
}
]
}
]
};
var i, j, merchant = null;
for(i = 0; i < data['industries'].length; i++){
if(data['industries'][i]['id'] == arg[0]['industry_Id']){
for(j = 0; j < data['industries'][i]['merchant'].length; j++){
if(data['industries'][i]['merchant'][j]['id'] == arg[0]['merchant_id']){
merchant = data['industries'][i]['merchant'][j];
break;
}
}
if(merchant !== null){ break; }
}
}
console.log(merchant);
document.writeln("<b>Without jQuery:</b><br>");
document.writeln((merchant !== null) ? "Found " + merchant['name'] : "Not found");
var merchant_found = null;
$.each(data['industries'], function(i, industry){
if(industry['id'] == arg[0]['industry_Id']){
$.each(industry['merchant'], function(i, merchant){
if(merchant['id'] == arg[0]['merchant_id']){
merchant_found = merchant;
}
return (!merchant_found);
});
}
return (!merchant_found);
});
console.log(merchant_found);
document.writeln("<br><br><b>With jQuery:</b><br>");
document.writeln((merchant_found) ? "Found " + merchant_found['name'] : "Not found");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
selectors.map(function(selector) {
return data.industries.filter(function(industry) {
return industry.id == selector.industry_Id;
})[0].merchant.filter(function(merchant) {
return merchant.id == selector.merchant_id;
})[0].name;
});
// => DEF
If you want "HP", you want industry 2, not industry 1.
.filter(...)[0] is not really optimal. You could use .find(...), but that is not yet universally supported. Or you could use plain old JavaScript and write for loops instead to make it fast. Or you could use objects with ID keys instead of arrays to make lookups faster.
When it comes into a position where collection of data is what you're processing, I suggest you to take a look at underscore.js. It's not optimal choice for the best performance but it does make you code more readable and makes more sense especially when compared with loop.
Say data is a variable which stores your JSON data.
Try this:
// Given this selector criteria
var select = [{"industry_Id":1,"merchant_id":2}];
function filterByCriteria(criteria, data){
var match = [];
_.each(criteria, function(crit){
function matchIndustry(rec){ return rec.id===crit.industry_Id }
function matchMerchant(rec){ return rec.id===crit.merchant_id }
// Filter by industry id
var industry = _.first(_.where(data.industry, matchIndustry));
// Filter by merchant id
var merchant = _.where(industry.merchant, matchMerchant);
_.each(merchant, function addToMatchResult(m){
match.push(m.name);
});
});
return match;
}
var filteredData = filterByCriteria(select, data);
From snippet above, any merchants which match the search criteria will be taken to the match list. Is it more readable to you?
Do you even need numerical id's? Gets super easy when you don't.
/*
{
"industry": {
"oil and gas":{
"merchant": {
"ABC": {
"name": "ABC oil"
},
"DEF": {
"name": "DEF gas"
},
"GHJ" :{
"name": "GHJ oil and gas"
}
}
},
"IT": {
"merchant": {
"Apple" : {
"name": "Apple computers"
},
"HP": {
"name": "Hewlett Packard"
},
"Google": {
"name": "Google. Maw haw haw"
}
}
}
}
}
*/
var data = '{"industry": {"oil and gas":{"merchant": {"ABC": {"name": "ABC oil"},"DEF": {"name": "DEF gas"},"GHJ" :{"name": "GHJ oil and gas"}}},"IT": {"merchant": {"Apple" : {"name": "Apple computers"},"HP": {"name": "Hewlett Packard"},"Google": {"name": "Google. Maw haw haw"}}}}}';
data = JSON.parse(data);
var merchant = data.industry['IT'].merchant['HP'];
alert(merchant.name);
//console.log(merchant.name);

programmatically add object properties of arrays

[
{
"uId": "2",
"tabId": 1,
"tabName": "Main",
"points": "10"
},
{
"uId": "3",
"tabId": 2,
"tabName": "Photography",
"points": "20"
}
]
how can I insert into specified array by inspecting its properties values? says I want to add a assoc object into uId = 3, how can I do that? or it's not possible technically?
This is also possible using array.map (Added to the ECMA-262 standard in the 5th edition):
array.map(function(i){
if(i.uId == 3) i['newprop'] = 'newValue';
});
Example Here.
Update: It could be an array
if(i.uId == 3) i['newprop'] = ['newvalue1', 'newvalue2'];
Example2 Here.
They look like JSON data , so json_decode() to an array , search for the UId value and then add the corresponding assoc value and after the end finally wrap them up using json_encode()
foreach($array as $k=>&$arr)
{
if($arr->{'uId'}==2)
{
$arr->{'somecol'}="Hey";
}
}
echo json_encode($array,JSON_PRETTY_PRINT);
OUTPUT :
[
{
"uId": "2",
"tabId": 1,
"tabName": "Main",
"points": "10",
"somecol": "Hey"
},
{
"uId": "3",
"tabId": 2,
"tabName": "Photography",
"points": "20"
}
]
var array = [
{
"uId": "2",
"tabId": 1,
"tabName": "Main",
"points": "10"
},
{
"uId": "3",
"tabId": 2,
"tabName": "Photography",
"points": "20"
}
];
for ( var i = 0; i < array.length; i++ ) {
if ( array[i].uId == 3) {
array[i].someProp = "Hello";
break; // remove this line for multiple updates
}
}
Or you can make a function like this:
function getMatch(data, uid) {
for ( var i = 0; i < data.length; i++ ) {
if ( data[i].uId == 3) {
return data[i];
}
}
}
and use it like this:
getMatch(array, 3).someproperty = 4;
You can use the map function, which executes a function on each element of an array
a.map(function(el) {
if (el.uId == 3) {
el.prop = "value";
}
});
Or you can use the filter function.
// Get the array of object which match the condition
var matches = a.filter(function(x) { return x.uId == 3 });
if (matches.length > 0) {
matches[0].prop = "value";
}

Categories

Resources