Loop through object and its array - javascript

Say i have an array with several objects, looking like this:
{
"firstname": John,
"lastname": "Doe",
"numbers": [{
"id": 1,
"value": "123"
}, {
"id": 2,
"value": "123"
}],
}, ...
How do i loop through these objects while also looping through their "numbers" property?

var input = {
"firstname": "John",
"lastname": "Doe",
"numbers": [{
"id": 1,
"value": "123"
}, {
"id": 2,
"value": "123"
}]
}
for (var key in input) {
if (key === "numbers") {
for (var i=0; i < input[key].length; i++) {
console.log(input[key][i]);
}
} else {
console.log(key + ":" + input[key])
}
}

Nested loop:
var input = [{
"firstname": John,
"lastname": "Doe",
"numbers": [{
"id": 1,
"value": "123"
}, {
"id": 2,
"value": "123"
}],
}]
input.forEach(function(item) {
item.numbers.forEach(function(number) {
console.log(number.id, number.value)
}
}

This one uses recursion so it will work even if the pattern isn't the same:
function looopAllTheThings(theThings, theCallback, depth){
if(undefined===depth) depth = 0;
if(typeof theThings == "object"){
for(var p in theThings)
if(theThings.hasOwnProperty(p))
if("object" == typeof theThings[p] ||
"array" == typeof theThings[p])
looopAllTheThings(theThings[p], theCallback, (depth+1));
else theCallback(p, theThings[p], depth);
}else if(typeof theThings == "array"){
for(var i=0; i<theThings.length; i++)
if("object" == typeof theThings[i] ||
"array" == typeof theThings[i])
looopAllTheThings(theThings[i], theCallback, (depth+1));
else theCallback(p, theThings[i], depth);
}else{
theCallback(null, theThings, depth);
}
}
Use it like this:
looopAllTheThings(data, function(key, value, depth){
document.getElementById('out').innerHTML += ("-".repeat(depth))+" "+key+" = "+value+"<br>";
});
Here's a fiddle: https://jsfiddle.net/2o2Lyayj/

Related

how to count similar value object in json?

I have this JSON structure:
[{
"name": "ankit",
"DOB": "23/06"
}, {
"name": "kapil",
"DOB": "26/06"
}, {
"name": "ankit",
"DOB": "27/06"
}]
I want to count similar object with value ankit. How can I do this?
You can use Array.prototype.filter():
var count = json.filter(function (el) {
return el.name == 'ankit';
}).length;
How about:
let a = [
{ "name": "ankit", "DOB": "23/06" },
{ "name": "kapil", "DOB": "26/06" },
{ "name": "ankit", "DOB": "27/06" }
];
let count = 0;
a.forEach(item => {
if (item.name === "ankit") {
count++;
}
});
(code in playground)
You could use an object for counting and get the wanted count for a name with the name as property.
var data = [{ "name": "ankit", "DOB": "23/06" }, { "name": "kapil", "DOB": "26/06" }, { "name": "ankit", "DOB": "27/06" }],
count = {};
data.forEach(function (a) {
count[a.name] = (count[a.name] || 0) + 1;
});
console.log(count);
console.log(count['ankit']);
You can use the reduce method to reduce the items that have the name ankit to a number.
var items = [
{
name: 'ankit',
DOB: '23/06'
},
{
name: 'kapil',
DOB: '26/06'
},
{
name: 'ankit',
DOB: '27/06'
}
]
var numItems = items.reduce(function (count, item) {
return item.name === 'ankit' ? count + 1 : count
}, 0)
document.write('Number of items with the name `ankit`: ' + numItems)
1. Get the object from JSON:
var obj = JSON.parse(text);
2. Get your array filtered:
var count = obj.filter(function(obj) { return obj.name == "ankit" }).length;

How to get the key value from nested object

I am having below object where I am trying to get all the id values.
[{
"type": "test",
"id": "100",
"values": {
"name": "Alpha"
},
"validations": []
}, {
"type": "services",
"validations": [{
"id": "200",
"name": "John",
"selection": [{
"id": "300",
"values": {
"name": "Blob"
}
}]
}]
}]
Using the below code, I am getting only the first id value. Is there any way to get all the id values from the nested object without using any external module.
for (var prop in obj) {
console.log(prop)
if (prop === key) {
set.push(prop);
}
}
Expected Output
[100,200,300] //all id values
You can use a JavaScript function like below to get the nested properties:
function findProp(obj, key, out) {
var i,
proto = Object.prototype,
ts = proto.toString,
hasOwn = proto.hasOwnProperty.bind(obj);
if ('[object Array]' !== ts.call(out)) out = [];
for (i in obj) {
if (hasOwn(i)) {
if (i === key) {
out.push(obj[i]);
} else if ('[object Array]' === ts.call(obj[i]) || '[object Object]' === ts.call(obj[i])) {
findProp(obj[i], key, out);
}
}
}
return out;
}
Check this Fiddle for a working solution.
Using Object.keys
function findProp(obj, prop) {
var result = [];
function recursivelyFindProp(o, keyToBeFound) {
Object.keys(o).forEach(function (key) {
if (typeof o[key] === 'object') {
recursivelyFindProp(o[key], keyToBeFound);
} else {
if (key === keyToBeFound) result.push(o[key]);
}
});
}
recursivelyFindProp(obj, prop);
return result;
}
// Testing:
var arr = [{
"type": "test",
"id": "100",
"values": {
"name": "Alpha"
},
"validations": []
}, {
"type": "services",
"validations": [{
"id": "200",
"name": "John",
"selection": [{
"id": "300",
"values": {
"name": "Blob"
}
}]
}]
}];
console.log(findProp(arr, "id"));
To get the keys from nested objects, you first need to put your code in a function, then for each of the top-level keys, check if it's an array or object. If it is, just call your function again from within that function (weird, I know.) Just make sure you don't skip the check of whether it's an object. You'll get stuck in an infinite loop. Something like this:
function parseObjectKeys(obj) {
for (var prop in obj) {
console.log(prop)
var sub = obj[prop]
if (typeof(sub) == "object") {
parseObjectKeys(sub);
}
}
}
Here's a more complex example:
https://jsfiddle.net/tfqLnzLm/1/
You can use a XPath styled json parser like JSONPath. The version I'm presenting here is a extended version I did here:
function jsonPath(obj,expr,arg){var P={resultType:arg&&arg.resultType||"VALUE",result:[],normalize:function(e){var t=[];return e.replace(/[\['](\??\(.*?\))[\]']/g,function(e,r){return"[#"+(t.push(r)-1)+"]"}).replace(/'?\.'?|\['?/g,";").replace(/;;;|;;/g,";..;").replace(/;$|'?\]|'$/g,"").replace(/#([0-9]+)/g,function(e,r){return t[r]})},asPath:function(e){for(var t=e.split(";"),r="$",a=1,n=t.length;n>a;a++)r+=/^[0-9*]+$/.test(t[a])?"["+t[a]+"]":"['"+t[a]+"']";return r},store:function(e,t){return e&&(P.result[P.result.length]="PATH"==P.resultType?P.asPath(e):t),!!e},trace:function(e,t,r){if(e){var a=e.split(";"),n=a.shift();if(a=a.join(";"),t&&t.hasOwnProperty(n))P.trace(a,t[n],r+";"+n);else if("*"===n)P.walk(n,a,t,r,function(e,t,r,a,n){P.trace(e+";"+r,a,n)});else if(".."===n)P.trace(a,t,r),P.walk(n,a,t,r,function(e,t,r,a,n){"object"==typeof a[e]&&P.trace("..;"+r,a[e],n+";"+e)});else if(/,/.test(n))for(var l=n.split(/'?,'?/),s=0,c=l.length;c>s;s++)P.trace(l[s]+";"+a,t,r);else/^\(.*?\)$/.test(n)?P.trace(P.eval(n,t,r.substr(r.lastIndexOf(";")+1))+";"+a,t,r):/^\?\(.*?\)$/.test(n)?P.walk(n,a,t,r,function(e,t,r,a,n){P.eval(t.replace(/^\?\((.*?)\)$/,"$1"),a[e],e)&&P.trace(e+";"+r,a,n)}):/^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$/.test(n)&&P.slice(n,a,t,r)}else P.store(r,t)},walk:function(e,t,r,a,n){if(r instanceof Array)for(var l=0,s=r.length;s>l;l++)l in r&&n(l,e,t,r,a);else if("object"==typeof r)for(var c in r)r.hasOwnProperty(c)&&n(c,e,t,r,a)},slice:function(e,t,r,a){if(r instanceof Array){var n=r.length,l=0,s=n,c=1;e.replace(/^(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)$/g,function(e,t,r,a){l=parseInt(t||l),s=parseInt(r||s),c=parseInt(a||c)}),l=0>l?Math.max(0,l+n):Math.min(n,l),s=0>s?Math.max(0,s+n):Math.min(n,s);for(var o=l;s>o;o+=c)P.trace(o+";"+t,r,a)}},eval:function(x,_v,_vname){try{return $&&_v&&eval(x.replace(/#/g,"_v"))}catch(e){throw new SyntaxError("jsonPath: "+e.message+": "+x.replace(/#/g,"_v").replace(/\^/g,"_a"))}}},$=obj;return expr&&obj&&("VALUE"==P.resultType||"PATH"==P.resultType)?(P.trace(P.normalize(expr).replace(/^\$;/,""),obj,"$"),P.result.length?P.result:!1):void 0}
// some extensions I have added to JSONPath
var jsonPathStore = function(obj,path,values) {
var maps=jsonPath(obj, path,{resultType:"PATH"})
maps.map(function(item,index) {
return eval( '(' + item.replace(/\$/,"obj") + '="' + values[index] +'"' + ')' );
})
}
var jsonPathDelete = function(obj,path) {
var maps=jsonPath(obj, path,{resultType:"PATH"})
maps.map(function(item,index) {
return eval( '(' + 'delete ' + item.replace(/\$/,"obj") + ')' );
})
}
var jsonPathRead = function(obj,path) {
var maps=jsonPath(obj, path,{resultType:"PATH"})
return maps.map(function(item,index) {
return eval( '(' + item.replace(/\$/,"obj") + ')' );
})
}
var jsonObject = [{
"type": "test",
"id": "100",
"values": {
"name": "Alpha"
},
"validations": []
}, {
"type": "services",
"validations": [{
"id": "200",
"name": "John",
"selection": [{
"id": "300",
"values": {
"name": "Blob"
}
}]
}]
}]
// this XPath will read all the id properties starting from the root element
console.log( "jsonPathRead All Ids" + JSON.stringify(jsonPathRead(jsonObject,"$..id"), null, 2) )
function getIds(obj) {
for (var x in obj) {
if (typeof obj[x] === 'object') {
getIds(obj[x]);
} else if (x === 'id') {
console.log(obj.id);
}
}
}

Compare two arrays and update with the new values by keeping the existing objects using javascript

Below are my two arrays .I want to compare them and the resultant array should contain the updated values.Id's are common..
The arrays spans to n levels ie., there is no fixed levels..
The first array ie., the array before updation..
var parentArray1=[
{
"id": 1,
"name": "test",
"context": [
{
"id": 1.1,
"name": "test 1.1"
}
]
},
{
"id": 2,
"name": "test"
},
{
"id": 3,
"name": "test",
"context": [
{
"id": 3.1,
"name": "test 3.1"
}
]
},
{
"id": 4,
"name": "test"
}
]
The operations that i performed are
1.Adding a new Item
2.Updating an existing item
As a result of these two operations the changed values I will be getting in a different array..
ie.,
var changedArray=
[
{
"id": 1,
"name": "test1",
"context": [
{
"id": 1.1,
"name": "Changed test 1.1"
}
]
},
{
"id": 5,
"name": "test5"
}
]
Now I have written a generic function that loops through the parentArray1 and using the unique propertiesI need to either add a new item,if the item is there in the changedArray or update an existing item at any level
The resultant array should be ..
[
{
"id": 1,
"name": "test",
"context": [
{
"id": 1.1,
"name": "Changed test 1.1"
}
]
},
{
"id": 2,
"name": "test"
},
{
"id": 3,
"name": "test",
"context": [
{
"id": 3.1,
"name": "test 3.1"
}
]
},
{
"id": 4,
"name": "test"
},
{
"id": 5,
"name": "test5"
}
]
Generic function:
compareArray(parentArray1, changedArray, ["id"]);
function compareArray(array1, array2, propertyArray) {
var newItem = new Array();
array2.map(function(a1Item) {
array1.map(function(a2Item) {
/ If array loop again /
if (a2Item.constructor === Array) {
compareArray(a2Item, a1Item)
} else {
/ loop the property name to validate /
propertyArray.map(function(property) {
if (a2Item[property]) {
if (a2Item[property] === a1Item[property]) {
a2Item = a1Item
} else {
var isAvailable = _.find(newItem, function(item) {
return item[property] === a1Item[property]
})
if (!isAvailable) {
newItem.push(a1Item);
}
}
}
})
}
});
});
/ Insert the new item into the source array /
newItem.map(function(item) {
array1.push(item);
});
console.log("After Compare : " + array1);
}
I suggest to use a temporary object for the reference to the id and update if exist or push if not exist.
var parentArray1 = [{ "id": 1, "name": "test", "context": [{ "id": 1.1, "name": "test 1.1" }] }, { "id": 2, "name": "test" }, { "id": 3, "name": "test", "context": [{ "id": 3.1, "name": "test 3.1" }] }, { "id": 4, "name": "test" }],
changedArray = [{ "id": 1, "name": "test1", "context": [{ "id": 1.1, "name": "Changed test 1.1" }] }, { "id": 5, "name": "test5" }];
function insert(array, data) {
function iter(array) {
array.forEach(function (a) {
if (!('id' in a)) {
return;
}
if (o[a.id] !== a) {
o[a.id] = a;
}
Object.keys(a).forEach(function (k) {
Array.isArray(a[k]) && iter(a[k]);
});
});
}
var o = {};
iter(array);
data.forEach(function (a) {
if (o[a.id]) {
Object.keys(a).forEach(function (k) {
o[a.id][k] = a[k];
});
return;
}
array.push(a);
});
}
insert(parentArray1, changedArray);
document.write('<pre>' + JSON.stringify(parentArray1, 0, 4) + '</pre>');
This is what I came up with:
function sameKeys(o1, o2, keys) {
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (!o1.hasOwnProperty(key) || !o2.hasOwnProperty(key))
throw 'compared objects do not have the key ' + key;
if (o1[key] !== o2[key])
return false;
}
return true;
}
function isNothing(o) {
return typeof(o) === 'undefined' || o === null;
}
// this does not work if objects have functions as properties
function clone(o) {
if (isNothing(o))
return o;
return JSON.parse(JSON.stringify(o));
}
function extend(o1, o2, keys) {
if (isNothing(o2))
return;
if (isNothing(o1))
throw ('first parameter cannot be empty');
if (typeof(o1) != 'object' || typeof(o2) != 'object')
throw ('extend only works on objects');
Object.keys(o2).forEach(function (key) {
var newVal = o2[key];
if (o1.hasOwnProperty(key)) {
if (isNothing(newVal)) {
delete o1[key];
} else
if (Array.isArray(newVal)) {
compareArray(o1[key], newVal, keys);
} else {
switch (typeof(newVal)) {
case 'object':
extend(o1[key], newVal, keys);
break;
case 'boolean':
case 'number':
case 'string':
o1[key] = newVal;
break;
default:
throw 'not supported property type: ' + typeof(newVal);
}
}
} else {
o1[key] = clone(newVal);
}
});
}
function removeFromArray(arr, ids, keyArray) {
var indexes = [];
var it1s = arr.forEach(function (it, idx) {
if (sameKeys(ids, it, keyArray)) {
indexes.push(idx);
} else {
Object.keys(it).forEach(function (key) {
var newVal = it[key];
if (Array.isArray(newVal)) {
removeFromArray(it[key], ids, keyArray);
}
});
}
});
if (indexes.length) {
if (indexes.length > 1)
throw 'found multiple possible objects for the same key combination'
arr.splice(indexes[0], 1);
}
}
function compareArray(a1, a2, keyArray) {
a2.forEach(function (it2) {
var it1s = a1.filter(function (it) {
return sameKeys(it2, it, keyArray);
});
var it1;
if (!it1s.length) {
it1 = clone(it2);
a1.push(it1);
} else {
if (it1s.length > 1)
throw 'found multiple possible objects for the same key combination'
it1 = it1s[0];
extend(it1, it2, keyArray);
}
if (it2.removedIds) {
it2.removedIds.forEach(function (ids) {
removeFromArray(a1, ids, keyArray);
});
}
});
}
Use it with compareArray(parentArray1,changedArray,['id']);
Note that it would not work with objects that contain functions. Also, if the arrays would be large, perhaps a better solution is to sort both arrays by key, then always look from the last found object up. That's all I got for now.
Updated it with some concepts from Nina and some clearing of the code.
As I understood it, you only want to add properties. So extend({a: {b: 2}},{a:{c:3}}) will result in {a: {b:2,c:3}}. If this is not what you wanted, let me know.
I also added functionality for removing ids. If any of the objects in the array contains a removedIds array of the form [{id: 4},{id: 5}] then the items with those ids will be removed from the original array.
Slight modification on code, to satisfy your conditions. Try it!
function compareArray(originalArray, destinationArray, propertyArray) {
var newItem = new Array(), processedItem = new Array();
for (var i = 0; i < originalArray.length; i++) {
var sourceElement = originalArray[i];
for (var j = 0; j < destinationArray.length; j++) {
var destinationElement = destinationArray[j];
var isUpdated = false;
if (sourceElement.constructor === Array) {
compareArray(sourceElement, destinationElement, propertyArray);
} else {
/* loop the property name to validate */
propertyArray.map(function(property) {
if (sourceElement[property]) {
if (sourceElement[property] === destinationElement[property]) {
originalArray[i] = _.clone(destinationElement);
isUpdated = true;
return;
} else {
var isAvailable = _.find(newItem, function(item) {
return item[property] === destinationElement[property];
});
if (!isAvailable) {
var isAlreadyProcessed = _.find(processedItem, function(item) {
return item[property] === destinationElement[property];
});
if(!isAlreadyProcessed){
newItem.push(destinationElement);
}
}
}
}
});
}
if (isUpdated === true) {
break;
}
}
processedItem.push(sourceElement);
}
newItem.map(function(item) {
originalArray.push(item);
});
return originalArray;
}

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);

Categories

Resources