How can I loop this (JSON) - javascript

{
"fulltime": [
{"name": "oscar godson", "age": "20", "email": "oscargodson#hismail.com"},
{"name": "daniel erickson", "age": "25", "email": "daniel#wraithtech.com"},
{"name": "john doe", "age": "18", "email": "john.doe#mycompany.com"}
],
"parttime":[
{"name": "bill johnson", "age": "35", "email": "billjohnson#gmail.com"}
]
}
and not knowing any of these values, e.g. fulltime could equal any thing. im looking for a function/method to loop through it all... Please, no jQuery.
Also, i want to basically get the output of: fulltime -> all inside of fulltime, parttime -> all inside of parttime, etc

for (key in your_object) {
console.log(key + " people:");
// "key" is "fulltime", "parttime", etc
for (var i = 0; i < your_object[key].length; i++) {
console.log(your_object[key][i]);
}
}

Supposing you have Firebug installed:
for(var key in json) {
//"fulltime", "parttime"
console.log("Checking " + key);
for(var i = 0; i < json[key].length; i++){
var person = json[key][i];
//Each person
for(var prop in person) {
console.log(prop + ": " + person[prop]);
}
}
}
Edit: Be careful that you don't iterate with for ... in ... over an array. To iterate over an array, use the "regular" way with for(var i = 0; i < array.length; i++){...}

You can do that with a recursive function. But you need to be careful about circular references. See example below:
var arr = [];
/**
* Gets the string representation of the specified object. This method is
* used for debugging
* #param {Object} Object to convert to string
* #return {String} The string representation of the object
*/
var toObjectSource = function(obj) {
if(obj === null) {
return "[null]";
}
if(obj === undefined) {
return "[undefined]";
}
var str = "[";
var member = null;
for(var each in obj) {
try {
member = obj[each];
if(arr.indexOf(member) === -1) { // the indexOf function is not available
// on older versions of js
arr.push(member);
str += each + "=" + toObjectSource(member) + ", "; // but beware of this
// recursive call!!!
}
}catch(err) {
alert(err);
}
}
return str + "]";
}
The reason for the check is that. It will give you "too much recursion" in case the object is like this:
var obj = {
"a": "a",
"b": "b"
}
obj.c = obj;

First of all you can verify your JSON data in http://www.jsonlint.com/.
If you not yet convert the string with JSON to the object you should use JSON.parse function from the web browser or from http://www.json.org/js.html to convert input string to the object.
For looping through the properties of a object you can use "for in" loop. It is generally always recommended to use this loop in the following form:
for (var name in myObject) {
if (myObject.hasOwnProperty(name)) {
// ....
}
}
(see for example http://www.jslint.com/lint.html#forin for the explanation). You should don't forget to declare name as var name either inside of for statement or somewhere before. If you forget this the variable will be interpret as a global and your code will run slowly.
Loop through element of an array in more effective with a standard for loop instead of "for in" loop. Moreover to receive more performance advantages you should always cache an index of a property used more as one time in a local variable. For example the the loop
for (var i = 0; i < your_object[key].length; i++) {
console.log(your_object[key][i]);
}
should be better rewritten as following:
var arr = your_object[key];
var len = arr.length;
for (var i = 0; i < len; i++) {
console.log(arr[i]);
}

Related

Javascript, loop through array and apply other functions

I have an array of objects,
var out = [{
"type": "1",
"from": "13052033555",
"to": "4444444",
"amount": "40000",
"date": 1461575799,
"status": "1"
}, {
"type": "2",
"from": "13052033555",
"to": "1111111",
"amount": "30000",
"date": 1461575884,
"status": "1"
}...
];
I get only it's values without keys
Now i used this function to get the values from array like this,
I pass array then it returns only values without keys
function foo(a) {
var values = [];
for (var i = 0; i < a.length; i++) {
var obj = a[i];
var arr = Object.keys(obj).map(function(k) {
return obj[k]
});
values.push("[" + arr + "],");
}
return values.join('');
}
Then it returns the values data without keys like this,
["1","13052033555","4444444","40000",1461575799,"1"],
["2","13052033555","1111111","30000",1461575884,"1"],
My question is how can I loop through the values and only apply a method to 5th value of each data array ?
All you have to do in foo is call your fn on arr[4] before continuing with the loop.
arr[4] = fn(arr[4])
This is of course, assuming you don't need to do this after the fact for whatever reason. If that is the case, you can use another for loop like your original code, and just modify the 5th element in each array as specified above, except it would look more like
for (var i = 0; i < outerArray.length; i++) {
outerArray[i][4] = fn(outerArray[i][4])
}
Now that we covered how to do it with your current code, I would also suggest that you don't do this for any real world application. If you want to modify data on a specific object property for a list of objects, you should do it with the object property name (key) and not later on the array of values using an index. This prevents any confusion that could arise from the fact that objects do not have a guaranteed order. Here's an example of how I would do this, assuming you want to modify date:
function foo(a) {
return a.map(function(obj) {
return Object.keys(obj).map(function(k) {
return k === 'date' ? fn(obj[k]) : obj[k]
})
})
}
This way you target the property you want but also don't modify the original object.
Note You should replace fn with your desired function :)
Edit Per your request, here is how you might extend it to check for other property names
function foo(a) {
return a.map(function(obj) {
var values = []
Object.keys(obj).forEach(function(k) {
if (k === 'date') {
values.push(fn(obj[k]))
} else if (k !== 'type') {
values.push(obj[k])
}
})
return values
})
}
var out = [{
"type": "1",
"from": "13052033555",
"to": "4444444",
"amount": "40000",
"date": 1461575799,
"status": "1"
}, {
"type": "2",
"from": "13052033555",
"to": "1111111",
"amount": "30000",
"date": 1461575884,
"status": "1"
}
];
function foo(a) {
var values = [];
for (var i = 0; i < a.length; i++) {
var obj = a[i];
var arr = Object.keys(obj).map(function(k) {
return obj[k]
});
values.push("[" + arr + "],");
}
return values.join('');
}
function myFn(elem){
console.log(elem);
return elem;
}
var arr = foo(out);
arr = JSON.parse("["+arr.substring(0,arr.length-1)+"]")
arr.forEach(function(elem){
return myFn(elem[4]);
});
console.log(arr);

Javascript arrays as objects [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Length of Javascript Object (ie. Associative Array)
Loop through JavaScript object
var location = {
"Steve": "New York",
"Abigayle": "Chicago"
}
for (var i = 0; i < location .length; i++)
{
console.log('works');
}
I'm trying to make an array, where each item has some name and value.
The code above doesn't work. Tryed to make an object, but it doesn't have a length property - no for loop.
location= {
"Steve": "New York",
"Abigayle": "Chicago"
};
Is it possible to use arrays in this context?
If you just want to work with what you have,
var location = {
"Steve" : "New York",
"Abigayle" : "Chicago"
}
for (var name in location) {
console.log( name, location[name] );
}
If you care about the length, use an Array of objects
var location = [
{ key : "Steve", value : "New York" },
{ key : "Abigayle", value : "Chicago" }
];
But there is no easy way to look it up, it would require a loop.
Just for reference, you can iterate over all the keys in an object:
location = {
"Steve": "New York",
"Abigayle": "Chicago"
};
for (var elem in location) {
console.log(elem);
}
Produces:
Steve
Abigayle
But I think that one of the other answers is probably the correct way to what you're looking for.
You can loop over object keys aswell. Only if you require indexed keys you should use an Array here.
var loc = {
"Steve": "New York",
"Abigayle": "Chicago"
};
Object.keys( loc ).forEach(function( name ) {
console.log('name: ', name, ' city: ', loc[ name ] );
});
By the way, location is a (pretty much) reserved variable name within the window object. You can't really overwrite that, so you should re-name that variable.
The above code uses Ecmascript 262 edition 5 code which works in all modern browsers. If you want to support legacy browsers you need to load any of the various ES5 shim libraries
var locations = [
["Steve","New York"]
,["Abigayle","Chicago"]
];
or
var locations = [
{Name:"Steve",Location:"New York"}
,{Name:"Abigayle",Location:"Chicago"}
];
you could output the data in the 1st option like this:
var delimiter = " ";
console.log("var locations = [");
for (var i=0; i<locations.length; i++)
{
var innerdelimiter = "";
var line = delimiter + "[";
for (var j=0; j<locations[i].length;j++)
{
line += innerdelimter + locations[i][j];
innerdelimiter = ",";
}
line += "]";
console.log(line);
delimiter = " ,";
}
console.log("];");
and data in the 2nd option like this:
var delimiter = " ";
console.log("var locations = [");
for (var key in locations)
{
console.log(delimiter + "{" + key + ":" + locations[key] + "}");
delimiter = " ,";
}
console.log("];");

Why did deserializing a serialized copy of my target array fix mem leak issues?

I have a 2 functions used for de-dup'ing and searching arrays. It's trivial stuff. I noticed that in some cases for arrays with over about 100 elements a huge memory leak would occur when using these functions and my node.js javascript app would die.
What could possibly be "wrong" with my array arr that would mean deserializing a serialized version of it fixes the mem leak? And why did deserializing a serialized copy of my target array fix mem leak issues?
Possibly related:
arr is built with a few dozen calls to concat.
The search function:
function findObjInArray(arr, obj, lookupKeyChain){
var tmpObj = undefined;
for(var i = 0; i < arr.length; i++){
tmpObj = arr[i];
for(var j = 0; j < lookupKeyChain.length; j++){
tmpObj = tmpObj[lookupKeyChain[j]]
if(!tmpObj){
break;
}else if(j==lookupKeyChain.length-1){
if(tmpObj==obj){
return arr[i];
}
}
}
}
return undefined;
}
The de-dupe function:
function combineProducts(productList, idKey){
var deDupedProducts = []
for(var i = 0; i < productList.length; i++){
var precedent = findObjInArray(deDupedProducts, productList[i][idKey], [idKey]);
if(precedent){
//just add tag data to precedent
for(var j = 0; j < productList[i].tags.length; j++){
precedent.tags.push(productList[i].tags[j]);
}
}else{
deDupedProducts.push(productList[i]);
}
}
return deDupedProducts;
}
An example of the structure in arr:
[
{
"price": "$9.99",
"name": "Big Widgets",
"tags": [
{
"tagClass": "Category",
"tagName": "On Sale"
}
]
},
{
"price": "$5.00",
"name": "Small Widgets",
"tags": [
{
"tagClass": "Category",
"tagName": "On Sale"
},
]
},
...
]
The call that causes the mem leak:
combineProducts(
arr,
"name"
)
The call that fixed the issue and gave me the correct result:
combineProducts(
JSON.parse(JSON.stringify(arr)),
"name"
)
Unrelated, but an object-based algorithm is much more efficient (and concise) for large lists than your ever-expanding linear search.
function combineProducts(productList, idKey) {
var lookup = {};
productList.forEach(function(product) {
var precedent = lookup[product[idKey];
if (precedent) {
precedent.tags = precedent.tags.concat(product.tags);
}
else {
lookup[product[idKey]] = product;
}
});
return Object.keys(lookup).map(function(idValue) {
return lookup[idValue];
});
}
Only difference to your function is that ordering is not preserved (though if the data was ordered by the idKey to start with, a single-pass algorithm would be even better).

What is the correct way to concatenate a string?

var d=getEntity( {"Division":
{
"oddTerms":
[
{
"entity": "Sunshine",
"Sunshine": [
{
"count": 2,
"entity": "Dodge"
},
{
"count": 1,
"entity": "Dodge Avenger"
},
]
}
]
}});
I want to traverse through the json string and the the entity names Dodge and Dodge Avenger. Ive used the following method
for (var k in h.Division.oddTerms)
{
s=h.Division.oddTerms[k].entity;
h.Division.oddTerms[k].+s+.entity;
}
But I do think this its not the correct methd to concatenate as it is not wrking.. anyone knows the correct format?
oddTerms is an Array, not an Object. For arrays in JavaScript you need to use a for loop with a counter instead of iterating through the elements:
var concatedString = '';
for (var k=0; k<h.Division.oddTerms.length;k++)
{
// Get the name of the entity we want to collect the entity terms of
var entityName =h.Division.oddTerms[k].entity;
// iterate through all the instances of each entity
for(var j=0; j<h.Division.oddTerms[k][entityName].length;j++){
concatedString += h.Division.oddTerms[k][entityName][j].entity;
}
}
var entityName = "",
arrTerms = [],
outputTemplate = '{"%entityName":[%terms]}',
h = {
"Division":
{
"oddTerms":
[
{
"entity": "Sunshine",
"Sunshine": [
{
"count": 2,
"entity": "Dodge"
},
{
"count": 1,
"entity": "Dodge Avenger"
},
]
}
]
}
};
for (var i = 0; i < h.Division.oddTerms.length; i++)
{
entityName=h.Division.oddTerms[i].entity; // "Sunshine"
terms = h.Division.oddTerms[i][entityName];
for (var j = 0; j < terms.length; j++) {
arrTerms.push('"' + terms[j].entity + '"');
}
}
// This will give you '{"Sunshine":["Dodge","Dodge Avenger"]}':
console.log(outputTemplate.replace('%entityName', entityName).replace('%terms', arrTerms.join(",")));
Edit:
Just some more on this.
JSON can be a bit confusing to work with if you're not used to working with JS and object and array "literals". In JS you can define objects and arrays in a number of ways, but the easiest (and the most preferred, by many developers) is with these literals.
Here's an example of an object:
var myObj = {
"some prop":"some value",
"anotherProp":"another value"
}
You can look up the members of myObj in several ways:
myObj.anotherProp // "another value"
myObj["some prop"] // you have to use this form if the property name has a space in it
For looping through the contents of an array, use the second form. For example, this won't work:
for (var strPropName in myObj) {
console.log(myObj.strPropName); // This won't work!
}
Instead, you should loop through the properties like this:
for (var strPropName in myObj) {
if (myObj.hasOwnProperty(strPropName)) {
console.log(myObj[strPropName]);
}
}
The if block is optional, but you'll avoid potential problems if you always include this in your code. It's also required by some validators.
Now, here's an example of an array:
var myArray = ["some value", "anotherValue"];
You access these with a numeric index:
myArray[0] // "some value"
myArray[1] // "anotherValue"
myArray[2] // undefined
And you can loop through them:
for (var index = 0; index < myArray.length; index++) {
console.log(myArray[index]);
}
You can nest objects inside arrays:
myArray = [{},{},{}];
And you can nest arrays inside objects:
myObject = {"arr1":[], "arr2":[], "arr3":[]}

JavaScript function, which reads connections between objects

I have a JavaScript literal:
var members = {
"mother": {
"name" : "Mary",
"age" : "48",
"connection": {
"brother" : "sun"
}
},
"father": {
"name" : "Bill",
"age" : "50"
},
"brother": {
"name" : "Alex",
"age" : "28"
}
}
Than I have a function, which should read connections from the literal above. It looks like this:
function findRelations(members){
var wires = new Array();
var count = 0;
for (n = 0; n < members.length; n++){
alert(members.length); // this alert is undefined
if (members[n].connection){
for (i = 0; i < members[n].connection[0].length; i++){
var mw = new Array();
var destination = 0;
for (m = 0; m < members.length; m ++){
if (members[m] == members[n].connection[0]){
destination = m;
mw = [n, destination];
wires [count] = mw;
count++;
}
}
}
}
}
return wires;
}
However, when I run this function, I get nothing. And the first alert, which is placed inside the function shows 'undefined' at all.
findRelations(members);
alert("Found " + wires.length + " connections");
I guess that's because of JavaScript literal. Could you suggest how to change a function or perhaps to change litteral to JSON array to get it work?! And at the end to get 'm' and 'n' values as numbers.
What is a 'literal'? I guess you mean 'an object created using the literal notation'.
Only Array's (and strings) have a length property, what you want is to loop through the properties
for (var prop in members) {
if (members.hasOwnProperty(prop)) {
alert("members has property " + prop);
}
}
This should get you on the right path as its not easy to follow the rest of the logic
The alert gives you "undefined" because your function seems to be expecting an array whereas your "members" variable is an Object.
the "length" property is not defined on an object. So,
var a = {
name:'test',
age:56
};
console.log(a.length); //undefined
The same is the reason for getting no response as well.

Categories