Retrieve index of an Object in javascript [duplicate] - javascript

This question already has answers here:
How do I loop through or enumerate a JavaScript object?
(48 answers)
Closed 5 years ago.
I've a javascript object inside a variable data like:
data: Object {
aliquota: 23,
imponibileLordo: 300,
imponibileScontato: "",
imposta: 69
}
In another function i've to iterate the object using an index like:
for ( var index = 0; index < data.length; index++ ) {
var valueOfIndex = data[index];
console.log(valueOfIndex);
}
But I get error cause data[0], data[1], data[2], data[3] are not defined.
How can solve this? Important: i've to use a numeric INDEX for cycle for cause I do other operation based on index value.
UPDATE: Ok my goal is another. So i'll upload the script i'm using with the fix I DON'T LIKE but works. (See //ACTUAL FIX comment) Also the fiddle here: https://jsfiddle.net/am3ovL3b/5/
var array_iva = [];
var data = { "impo": 10, "aliq": 20, "other": 30 };
var column = { "title": "TEST 1", "data": data };
array_iva.push(column);
var data = { "impo": 40, "aliq": 50, "other": 60 };
var column = { "title": "TEST 2", "data": data };
array_iva.push(column);
var json_righe = [[ "Imponibile lordo" ], [ "Aliquota %" ], [ "Others" ] ];
for ( var i = 0; i < array_iva.length; i++ ) {
var titolo_colonna_iva = {};
titolo_colonna_iva['title'] = array_iva[i]['title'];
for ( j = 0; j < json_righe.length; j++ ) { // for each
var riga = json_righe[j];
for ( var k = 0; k < array_iva.length; k++ ) { // EMPTY DEFAULT
riga.push("");
}
// ACTUAL FIX
if ( j == 0 ) {
riga[(i+1)] = array_iva[i]['data']['impo'];
} else if ( j == 1 ) {
riga[(i+1)] = array_iva[i]['data']['aliq'];
} else if ( j == 2 ) {
riga[(i+1)] = array_iva[i]['data']['other'];
}
//END ACTUAL FIX
/*
THIS DOESn?T WORK
riga[(i+1)] = array_iva[i]['data'][j];
*/
json_righe[j] = riga;
}
}

You can use Object.keys to get an array of all keys and loop trough this array to console.log value correponding to each key:
var data = {
aliquota: 23,
imponibileLordo: 300,
imponibileScontato: "",
imposta: 69
};
Object.keys(data).forEach(key => console.log(data[key]));

To iterate an object use for ..in
var data = {
aliquota: 23,
imponibileLordo: 300,
imponibileScontato: "",
imposta: 69
}
for (var index in data) {
var valueOfIndex = data[index];
console.log(valueOfIndex);
}

i've to use a numeric INDEX for cycle for cause I do other operation based on index value.
Then you'll want to reorganize your logic and code to use an array instead of an object, or at least to have your own array of property names in a defined order and loop through that. Although object properties have an order as of ES2015, it's not an order you should use as it depends on how the object was created and what the names of the properties are (e.g., do they look like array indexes or not).
You can loop through the object's properties in the ES2015+ order by using Object.getOwnPropertyNames on the object and looping through the strings in the returned array, e.g.:
Object.getOwnPropertyNames(data).forEach((name, index) => {
// `name` will be the property name,
// `index` will be its index in the property order
// ...
});
...but again, it's not a good idea to rely on those being in any particular order.

Related

how to count children in object in javascript?

I have a json array ..I want to refactor the json object ..but I am not able to make as expected output .I want to search all item or object and insert the children of parent ..I try like that
https://jsfiddle.net/nk6v0y36/1/
var new_Arry = [];
for (var i = 0; i < arry.length; i++) {
var obj = {};
var childeren = [];
obj.con_id = arry[i].con_id;
obj.children = [{
con_to: arry[i].con_to
}];
new_Arry.push(obj)
}
console.log(new_Arry)
Expected output:
[{
"con_id": 11,
"children": [{
"con_to": 12
}]
}, {
"con_id": 12,
"children": [{
"con_to": 13
}, {
"con_to": 14
}]
}, {
"con_id": 13,
"children": []
}, {
"con_id": 14,
"children": [{
"con_to": 15
}]
}, {
"con_id": 15,
"children": [{
"con_to": 16
}]
}, {
"con_id": 16,
"children": []
}]
After answer
https://jsfiddle.net/nk6v0y36/7/
Answer not working..
As thisOneGuy said, you are not checking if a con_id already exists in the new array, so for each element in the old array you are creating a corresponding new one. Your expected output though shows you want to merge these multiple con_id values into a single object.
You are also creating objects with con_to properties in the children arrays even when there is no such property, which again your expected output suggests you do not way.
One way to fix this would be:
var new_Arry = [];
var new_Hash = [];
for (var i = 0; i < arry.length; i++) {
if (new_Hash[arry[i].con_id] === undefined ) {
var obj = {
con_id: arry[i].con_id,
children: []
};
if( arry[i].con_to !== undefined ) {
obj.children.push({ con_to: arry[i].con_to });
}
new_Hash[obj.con_id] = new_Arry.push(obj) - 1;
} else if( arry[i].con_to !== undefined ) {
new_Arry[new_Hash[arry[i].con_id]].children.push({ con_to: arry[i].con_to });
}
}
console.log(new_Arry);
The key here is the new_Hash array, which uses the con_id value as its key, and stores the respective index in the new_Arry as its value.
So for each con_id in arry it first checks the new_Hash to see if there is an entry for it. If not then there is no entry in new_Arry, so it creates a new one.
Firstly the basic object, with con_id and a children array is created. It then checks whether there is a con_to property in arry, and only if there is does it add one as an object to the children array.
This object is then added to new_Arry and new_Hash updated so that an element for con_id references the new new_Arry index. As the .push() method returns extends an array and returns the new array length, the new index will always be this value minus one.
However if an entry for con_id was found in new_Hash then all you need to do it add the con_to value to the existing children array. Whilst presumably if there are multiple con_id entries in arry they must contain a con_to value, it also checks this just to be safe. The index number for the new_Arry as returned by new_Hash[arry[i].cond_id].
Incidentally, the reason for explicitly checking for undefined rather than seeing if value equates to true or false to check for its existence is a con_id or con_to value of 0 would be treated as false and skipped.
Like this -
var new_Arry = [];
for (var i = 0; i < arry.length; i++) {
var obj = {};
var childeren = [];
obj.con_id = arry[i].con_id;
var child = [];
var childrenObj = {};
childrenObj.con_to = arry[i].con_to;
child.push(childrenObj);
obj.children = child;
new_Arry.push(obj)
}
https://jsfiddle.net/nk6v0y36/3/
Here is the correct answer with the correct output : https://jsfiddle.net/nk6v0y36/4/
Basically you need to loop through your array to check if the con_id exists in that array, if it does, just add to children, if it doesnt add a new object.
var new_Arry = [];
for (var i = 0; i < arry.length; i++) {
var obj = {};
var childeren = [];
if (new_Arry.length > 0) {
console.log('start')
console.log(new_Arry.length);
var thisBool = false;
for (var j = 0; j <= new_Arry.length; j++) {
console.log('inside')
if (new_Arry[j]) {
if (new_Arry[j].con_id === arry[i].con_id) {
console.log('has children')
new_Arry[j].children[new_Arry[j].children.length] = {
con_to: arry[i].con_to
}
} else {
thisBool = true;
}
}
}
if(thisBool){
obj.con_id = arry[i].con_id;
obj.children = [{
con_to: arry[i].con_to
}];
new_Arry.push(obj)
}
} else {
console.log('no children')
obj.con_id = arry[i].con_id;
obj.children = [{
con_to: arry[i].con_to
}];
new_Arry.push(obj)
}
}
Check the output in the console log to see it's correct :)

iterate over json array - how to get the name / key of collection

I get a json object from an API ; I'm getting (inside another collection - but that doesn't matter) a collection of keys like so:
{ "Id": "64a66e2c-38fa-41dd-9183-8b1bd18a3c87",
"fields": [
{ "Name": "x1" },
{ "Name": "x2" },
{ "Name": "x3" }
],
"weeks": [ "2015-25", "2015-26", "2015-27" ],
"series": {
"M1": [ 6376, 17877, 22592 ],
"M2": [ 700, 702, 702 ],
"M3": [ null, 1, 1 ],
"M4": [ null, 5889, 10275 ]
}
}
the series itself (like M1) have values (1 - 1 etc) I can read and use,
but I actually need the name of the serie (like "M1").
So I iterate over the collection series and over each values within that serie without any difficulty, but how do I get the name of the serie itself - that name is (not in this example) quite descriptive and usefull
$.each(data.series, function (rowIndex, row) {
var attempt = data.series[rowIndex]; // nope this is [1,1,1,2] or something
for (var i = 0; i < row.length; i++) {
var value = row[i]; // yep this is one of the values
};
});
how do I get "serie1" into var attempt?
You already get the key as the first param when passing in a javascript object to the $.each() iterator.
$.each(data.series, function (rowIndex, row) {
window.alert(rowIndex);
});
I think what everyone is trying to say is that a more descriptive signature of the jquery.each callback is:
$.each(data.series, function (key, val) {
var attempt = data.series[key]; // nope this is [1,1,1,2] or something
for (var i = 0; i < val.length; i++) {
var value = val[i]; // yep this is one of the values
};
});
so to get what you want, simple change to:
$.each(data.series, function (key, val) {
var attempt = key;
for (var i = 0; i < val.length; i++) {
var value = val[i];
};
});

Finding MODE Iterating through FOR Loop for multiple arrays

Desired:
I have multiple arrays of players, roundWinners, being iterated through in a FOR loop. For each array, I need the MODE of the array (the most frequently occurring value) assigned to a new variable winner.
I am lost as to where to start, so I ask what is the most efficient way to go about accomplishing this?
Example:
for (i = 0; i < numberOf; i++) {
var roundWinners[0] = ["Joe", "Joe", "Bob", "Sue"]
var winner[0] ="Joe";
var roundWinners[1] = ["Joe", "Sue", "Bob", "Sue"]
var winner[1] ="Sue";
var roundWinners[2] = ["Bob", "Bob", "Bob", "Sue"]
var winner[2] ="Bob";
}
Prior to the loop, create an object.
var ArrMode = {};
Then, on each iteration, take the name, and, using it as a property name, see if the object has a property of that name. If so, increment the value of that property.
If not, add that property, setting its value to 1.
After processing the array, then process the object, using a simple replace-if-greater test. Each time you make a replacement, hold the name of that property as the winner.
Once you have processed the whole object, the property name you are holding is the name of the winner.
I don't actually have an answer
One person posted this as a way to iterate through the properties of a JS object, when you do not know the property names at design time:
for (var property in object) {
if (object.hasOwnProperty(property)) {
// do stuff
}
}
You can add a property to a JS object at any time, using:
obj[theName] = theVal; // the name’d be a string, theVal’d be anything
// Like:
var theName = "John";
obj[theName] = 1;
So, you would create an empty object before the loop with a name (like, say "modes"), but no properties
var modes = {};
Then, in each iteration over the array, iterate through the object's properties, checking the name of the properties against the current name in the array.
If found, then use:
modes[arr[i]]++;
If not found, then use
modes[arr[i]] = 1;
After the iterating over the array, iterate over the object's properties, checking their values, and 'remembering' the name and value of the highest one.
Working:
//Mode Calc
function mode( arr ) {
if ( !Array.isArray( arr ) ) {
throw new TypeError( 'mode()::invalid input argument. Must provide an array.' );
}
var len = arr.length,
count = {},
max = 0,
vals = [],
val;
for ( var i = 0; i < len; i++ ) {
val = arr[ i ];
if ( !count[ val ] ) {
count[ val ] = 0;
}
count[ val ] += 1;
if ( count[ val ] === max ) {
vals.push( val );
} else {
max = count[ val ];
vals = [ val ];
}
}
return vals.sort( function sort( a, b ) {
return a - b;
});
} // end FUNCTION mode()
for (i = 0; i < numberOf; i++) {
winner = ( mode( roundWinners[i] ) );
}

Combining results into one object

I'm looping through a set of inputs. I need to tally up the grouped totals. The inputs below to one of three categories.
How do I go about combining the values up relevant to three categories?
var compoundedArray = new Array();
holder.find(".dataset input").each(function(index) {
var val = $(this).val();
var dataType = $(this).data("type");
var localObj = {};
localObj[dataType] = val;
compoundedArray.push(localObj);
});
I have an object like this
[
{
"growth":30
},
{
"growth": 40
},
{
"other": 20
}
]
how do I loop through the object to produce something like
[
{
"growth": 70
},
{
"other": 20
}
]
if I looped over the initial array object
for (var i = 0; i < compoundedArray.length; i++) {
console.log(compoundedArray[i]);
}
how would I go about checking to ensure I don't have duplicates - and that I can tally up the results?
Ideally the resulting format may be the best
var array = [
"matching": 50,
"growth": 20
]
var array = [
"matching": 50,
"growth": 20
]
is not valid JS, but you can create an object of the form
var obj = {
"matching": 50,
"growth": 20
};
And that's pretty easy to do, just use an object from the very beginning:
var result = {};
holder.find(".dataset input").each(function(index) {
var val = +$(this).val(); // use unary plus to convert to number
var dataType = $(this).data("type");
result[dataType] = (result[dataType] || 0) + val;
});
Further reading material:
MDN - Working with Objects
Eloquent JavaScript - Data structures: Objects and Arrays
You can just use an object (not array) with unique keys.
var compoundedObj = {};
$(".dataset input", holder).each(function() {
var dataType = $(this).data("type");
if(!compoundedObj.hasOwnProperty(dataType)) {
compoundedObj[dataType] = 0;
}
compoundedObj[dataType] += parseInt($(this).val(), 10);
});
In this way you'll get an object like this:
{
"growth": 70,
"other": 20
}
Live demo
http://jsfiddle.net/GFwGU/
var original = [{"growth":30},{"growth": 40},{"other": 20}]
// object to sum all parts by key
var sums = {}
// loop through original object
for(var index in original){
// get reference to array value (target object)
var outer = original[index]
// loop through keys of target object
for(var key in outer){
// get a reference to the value
var value = outer[key]
// set or add to the value on the sums object
sums[key] = sums[key] ? sums[key] + value : value
}
}
// create the output array
var updated = []
// loop through all the summed keys
for(var key in sums){
// get reference to value
var value = sums[key]
// create empty object
var dummy = {}
// build object into desired format
dummy[key] = value
// push to output array
updated.push(dummy)
}
// check the results
alert(JSON.stringify( updated ))
var add=function (a,b){ a=a||0; b=b||0; return a+b};
var input=[ {growth:30},{growth:40},{other:20} ],output=[],temp={};
$.each(input,function(i,o){
var n;
for(i in o)
{n=i;break}
temp[n]=add(temp[n],o[n]);
});
$.each(temp,function(i,o){
var k={};
k[i]=o;
output.push(k)
});

javascript associative array access by key value

I have an array like this:
employees = [
{
"id": 1,
"shift_id": 1,
"days": {
"2012-03-01": 1,
"2012-03-02": 1,
"2012-03-03": 1,
"2012-03-04": 0,
"2012-03-05": 0,
"2012-03-06": 0
}},
{
"id": 2,
"shift_id": 1,
"days": {
"2012-03-01": 0,
"2012-03-02": 1,
"2012-03-03": 1,
"2012-03-04": 1,
"2012-03-05": 1,
"2012-03-06": 0
}},
{
"id": 3,
"shift_id": 2,
"days": {
"2012-03-01": 0,
"2012-03-02": 0,
"2012-03-03": 1,
"2012-03-04": 1,
"2012-03-05": 1,
"2012-03-06": 1
}}
];
is there a way to access an element in this array using the id value?
maybe something in jquery?
like $(employees('id = 1');
Just loop through your array and check for the id:
var yourId = 1;
for (var i = 0, len = employees.length; i < len; i++) {
if (employees[i].id == yourId) {
// ...
}
}
You can use a function like this, which filters the array appropriately:
var getEmployee = function (id) {
return employees.filter(function(i) { return i.id == id; });
};
You can use .grep() method documented here:
var employee = $.grep(employees, function(e) { return e.id == 1 })[0];
Well, there's a jQuery way of doing it:
var findElementById = function(elements, id) {
return $.grep(elements, function(e) { return e.id === id; })[0];
}
Still I wonder why don't you just index the source array by id instead.
Maybe you are looking for something like the below:
$.grep(employees, function(n){return n.id==1});
Or this:
$.each(employee, function(){
if(this["id"] == 2){
console.log(this);
}
});
As far as I am aware, in order to achieve that you would have to loop through them
Array.prototype.getObjectById = function(x){
var catcher = false, i = 0;
while(!catcher){
catcher = this[i].id == x ? this[i] : false;
i++;
}
return catcher;
}
This function should help. It will extend the array object so you can use it as myArray.getObjectbyId(id);
By design, this will return the first object that meets the criteria. You could extend it like so:
Array.prototype.getObjectsById = function(x){
var catcher = [], i = 0;
for(var i = 0; i < this.length; i++){
if(this[i].id == value){
catcher.push(this[i]);
}
i++;
}
return catcher.length == 1 ? catcher[0] : catcher;
}
This will return an array of objects if more than one object matches the criteria.
Array.prototype.getObjectsByAttribute = function(x, criteria){
if(!criteria){criteria = 'id';}
var catcher = [], i = 0;
for(var i = 0; i < this.length; i++){
if(this[i].criteria == value){
catcher.push(this[i]);
}
i++;
}
return catcher.length == 1 ? catcher[0] : catcher;
}
This extends it further to look for any criteria.
I know this question is old, but for future reference if anyone else stumbles upon this question ...
Instead of trying to over-engineer a function to parse/examine your JSON, consider changing the structure of your data to suit its purpose.
Consider the example in the question:
data = [ {
"id": 1,
"shift_id": 1,
"days": {
"2012-03-01": 1,
"2012-03-02": 1,
"2012-03-03": 1,
"2012-03-04": 0,
"2012-03-05": 0,
"2012-03-06": 0
}}, { .. }, {...} ]
Structuring the data in this way only gives you sequential access to the objects with no way to lookup an object by a particular index. Array indices are generally meaningless in this context.
data[0] => { id : 1, .. }
data[1] => { id : 2, .. }
What happens if the id is non-sequential or alphanumeric?
Using an array wont help you search any faster, you'll still have to loop...
Instead consider using a hash table/object:
{
'id1' => { id : 1 , data : { ... } },
'id99' => { id : 99, data : { ... } },
'id2' => { id : 2 , data : { ... } },
}
You can use a string value for the key and get direct access to the data by doing something like:
data['id2'] => { id : 2, ... }
Which will give you direct access to the data you want to find (by id). By simply re-organizing the structure of the data we were able to go from a O(n) search to an O(1) search.
Keep in mind that this method may work better for some solutions than others, and there are a number of other considerations to make.
This is just one approach to how you might solve a problem when you want to lookup data by a unique property.
The accepted answer is great - modified a bit for an AngularJS app:
$rootScope.getObjectsByAttribute = function(inarry,infldnm,infldval){
// This will iterate through a fetchAll sql result set and return rows where fldnm==fldval
// If it finds 1 row it returns a single object, if more than that it returns an array of objects
// Usage: result = $rootScope.getObjectsByAttribute(myarray,'myfldnm',myfldval);
if(!infldnm){infldnm = 'id';}
var catcher = [], i = 0;
for(i = 0; i < inarry.length; i++){
if(inarry[i][infldnm] == infldval){
catcher.push(inarry[i]);
}
}
return catcher.length == 1 ? catcher[0] : catcher;
}

Categories