Javascript for loop var "i" is treated as a string? - javascript

I am using Titanium to build some mobile apps and I noticed that this will give a result that I wasn't expecting.
data = ['a','b', 'c','d'];
for (var i in data){
Ti.API.debug(i+1);
};
This will print: 01,11,12,13
Is this something particular to Titanium or is it generally in Javascript?
Why isn't 'i' being treated as an integer? I am very confused.
Thanks for your help.

This doesn't directly answer your question, but if you are looping through an array you should not use for (var i in data). This loops through all members of an object, including methods, properties, etc.
What you want to do is this:
for (var i=0, item; i<data.length; i++) {
item = data[i];
}

data is an array, so you use a for loop, not a for-in loop:
var data = [ ... ];
var i;
for ( i = 0; i < data.length; i += 1 ) {
Ti.API.debug( i + 1 );
}
Alternatively, you can use the forEach array method:
data.forEach( function ( val, i ) {
Ti.API.debug( i + 1 );
});

The reason why you see this behavior is that the type of i when using a for-in over an array is string not int. Hence the + is doing string concatenation and not addition. If you want it to be the numerical value then use a for loop
for (var i = 0; i < data.length; i++) {
Ti.API.debug(i + 1);
}

Try this:
data = ['a','b', 'c','d'];
for (var i in data){
Ti.API.debug(i*1+1);
};
Multiplying i x 1 will force it to recognize it as numeric.

Try this:
Ti.API.debug(parseInt(i)+1);

You can do
data = ['a','b', 'c','d'];
for (var i in data){
console.log(parseInt(i)+1);
};
But it is not recommended. Because in Javascript for..in loop is for key:value pairs (Objects). So if use it with an array each index is converted to string as key.
so always use for(i = 0; i < length; i++) with arrays.

This is because javascript handles for-each loop this way.
In other languages for(i in datas) will loop through each data.
But in javascript the i will have index value instead of data. so you have to get data by datas[i].

Related

JavaScript for loop Index becomes arrayIndex

I have the following JavaScript code fragment
var ip = new Array();
// This array filled with values and passed to function
function calculateTime(ip) {
for (i in ip) {
window.alert(i);
if (!i in myArray) {
myArray[i] = 0;
} else {
myArray[i] += 1;
}
}
}
I expect i to be an index (0, 1, 2 ...) but sometimes window.alert prints "arrayIndex" and because of that my code doesn't work correctly. Can someone explain me the reason? I am new in JavaScript.
for in will loop over all the enumerable properties of an object.
None of the properties that come with an array are enumerable in modern browsers, but any that are added (such as the normal array indexes or any custom named properties) will be.
Somewhere you have some code that is adding an arrayIndex property to your array and it is coming up when you loop over it.
var myArray = [];
myArray[0] = 1;
myArray[1] = 1;
myArray[2] = 1;
myArray.arrayIndex = 1;
for (prop in myArray) {
console.log(prop);
}
If you only want to get numerical indexes, then use a standard for loop.
for (var i = 0 ; i < myArray.length ; i++) {
console.log(i);
}
For arrays, you should use a numeric variable rather than in:
for(var i = 0; i < ip.length; i++)
in is to iterate over the keys of an Object, but even there you have to take much care to filter out inherited properties.
Now, since arrays are objects too in JavaScript, you can assign them object properties:
ip["arrayIndex"] = 'some value';
Then "arrayIndex" will show up in a for...in iteration, whereas in a "normal" for loop, it won't.
Use either
for(var i=0; i<ip.length; i++){
//your code
}
or
ip.forEach(function(val,i){
// your code
});
The for(var x in y) loop works best for Object rather than Array. When you use it on arrays it will loop through all properties including named ones like length not just numerical indices.

concat empty / single item array

Ok, so I have this simple code :
for(var i=0; i<lines.length; i++) {
elements += myFunction(lines[i]);
}
Where elements is an empty array at the start and myFunction() is just a function that returns an array of strings.
The problem is that if myFunction() returns an array with a single string, the += is interpreted as a string concat in place of an array concat.
At the end of the loop the result is just a long string and not an array.
I tried push()ing the values in place of concatenation, but this just gives me a two dimensional matrix with single item arrays.
How can I solve this typecasting problem ? Thank you in advance !
Try :
for(var i=0; i<lines.length; i++) {
elements [i] = myFunction(lines[i]);
}
I suppose it solves the problem.
You can use the Array concat function:
elements = elements.concat(myFunction(lines[i]));
Presumably you want something like:
var arrs = [[0],[1,2],[3,4,5],[6]];
var result = [];
for (var i=0, iLen=arrs.length; i<iLen; i++) {
result = result.concat(arrs[i]);
}
alert(result); // 0,1,2,3,4,5,6
Ah, you want to concatenate the results of a function. Same concept, see other answers.
You can also use myArray[myArray.length] = someValue;
let newArray = [].concat(singleElementOrArray)

Convert multidimensional array to array of objects in javascript

I have a multidimensional array (retdata[R][C]) that basically looks like a spreadsheet of cells. R represents the rows, C the columns. I want to create an array of objects so that I get the following
[{retdata[1][1]:retdata[2][1],retdata[1][2]:retdata[2][2],retdata[1][3]:retdata[2][3] },
{retdata[1][1]:retdata[3][1],retdata[1][2]:retdata[3][2],retdata[1][3]:retdata[3][3] },
{retdata[1][1]:retdata[4][1],retdata[1][2]:retdata[4][2],retdata[1][3]:retdata[4][3] },
etc...
]
The resulting array should be:
[{"Col1":"dataR2C1","Col2":"dataR2C2", "Col3":"dataR2C3"},
{"Col1":"dataR3C1","Col2":"dataR3C2", "Col3":"dataR3C3"},
{"Col1":"dataR4C1","Col2":"dataR4C2", "Col3":"dataR4C3"},
etc...
]
I have tried a number of options without success. Any help would be greatly appreciated.
Here is one example I have used but it id not serializing the objects properly.
var TABLE = [];
for (var i=2; i<=rows; i++) {
var ROW = {};
for (var j=1; j<=columns; j++){
name = retdata[1][j].toString;
value = retdata[i][j].toString;
ROW += {name: value}
}
TABLE += ROW;
}
This is like a CSV-parser, the first row of your table are the keys for the line-objects. Your function would work, but you need to correct your array indices: they always start at 0, running up to n-1. Also, you need to learn a bit JavaScript syntax:
something.toString does not call the toString function on that value, but gets that function (it's just an object).
You don't need toString at all - where needed, values are automatically casted
You can't add key-value-pairs to object with a simple operator. You will need to assign the value to that property of an object, with the bracket notation. The += operator would have casted the values to strings and concatenated them.
It's the same with arrays. You could use the .push() method, or just assign to a numerical key - the javascript array object will automatically update its length.
var retdata = […];
var table = [],
keys = retdata.shift(); // get & remove the first row
for (var i=0; i<retdata.length; i++) {
var row = {};
for (var j=0; j<retdata[i].length; j++)
row[ keys[j] ] = retdata[i][j];
table[i] = row;
}
Thank you Bergi. Here is my final solution:
var TABLE = [];
for (var i=2; i<=rows; i++) {
var ROW = {};
for (var j=1; j<=columns; j++){
ROW [retdata[1][j]] = retdata[i][j];
}
TABLE[i]= ROW;
}
which works. The shift did not work as expected but above code is just what I needed. Thanks!

Javascript: Iterating over array with non-consecutive keys

I need to iterate over an array for which the keys are non-consecutive:
var messages = new Array();
messages[0] = "This is the first message";
messages[3] = "This is another message";
Obviously using the index of a for loop will not work as it depends on the keys being sequential:
for (var i=0 ; i<messages.length ; i++) {
alert(messages[i]); // Will only alert the first message, as i is never equal to 3
}
What is the canonical way of dealing with this, seeing as the for-each syntax is not intended for iterating over values in an array in javascript? Thanks.
The idiomatic way would be to use an object, not an array. Just be sure to check hasOwnProperty to make sure you don't pick up stray things which may have been added to the prototype.
var messages = { };
messages[0] = "This is the first message";
messages[3] = "This is another message";
for (var i in messages) {
if (messages.hasOwnProperty(i))
alert(messages[i]);
}
Or, the more modern way would be to use Object.keys
Object.keys(messages).forEach(prop => {
alert(messages[prop]);
});
Be sure to transpile that code with Babel if you plan on running it in older browsers like IE.
for(var i in messages)
{
console.log(messages[i]);
}
You could ignore the undefined properties...
for (var i=0 ; i<messages.length ; i++) {
if(messages[i] !== undefined)
alert(messages[i]);
}
Or use forEach, which will ignore undefined undeclared properties...
messages.forEach(function(v,i) {
alert(v);
});
Simple! if the array has regular gaps between the indices do this:
for (var i = 0 ; i < messages.length; i += gap) {
alert(messages[i]); // Will only alert the messages at the regular interval/gap
}
You can use each() jQuery method to do this.
$.each(messages, function(index, val){
alert(val);
});
From jQuery docs
each()
A generic iterator function, which can be used to seamlessly iterate
over both objects and arrays. Arrays and array-like objects with a
length property (such as a function's arguments object) are iterated
by numeric index, from 0 to length-1. Other objects are iterated via
their named properties.
When you create an array and give it values at 0 and 3, undefined values are created at 1 and 2. try this:
$.each(messages, function(i,val) {
if (val) {
alert(val);
}
});
For a use case such with the assumptions:
array.length >== 1
(i.e: an array with meaningful data in it already)
Where you are interested in the data from array[1], array[15], array[45] etc
You can do something similar to:
var array = ["you","will","become","strong","with","the","codes","padawan"];
var values = [1,5,7];
for (var i = 0; i < values.length; i++){
var cypher = values[i];
console.log(array[cypher]);
}
//will, the, padawan
Or perhaps something more meaningful such as:
for (var i = 0; i < values.length; i++){
var cypher = values[i];
aService.aFn.(array[cypher],cb);
}
//calls aService.aFn separately for each value array[1] , array[5] , array[7] passed as args

Loop through associative array in reverse

I'm using a javascript associative array (arr) and am using this method to loop through it.
for(var i in arr) {
var value = arr[i];
alert(i =") "+ value);
}
The problem is that the order of the items is important to me, and it needs to loop through from last to first, rather than first to last as it currently does.
Is there a way to do this?
Four things:
JavaScript has arrays (integer-indexed [see comments below]) and objects (string-indexed). What you would call an associative array in another language is called an object in JS.
You shouldn't use for in to loop through a JS array.
If you're looping through an object, use: hasOwnProperty.
JavaScript doesn't guarantee the order of keys in an object. If you care about order, use an array instead.
If you're using a normal array, do this:
for (var i = arr.length - 1; i >= 0; i--) {
//do something with arr[i]
}
Warning: this answer is ancient.
If you're here for a quick fix, kindly refer to the much better answer below.
Original answer retained, because reasons. See comments.
Using a temporary array holding the keys in reverse order:
var keys = new Array();
for (var k in arr) {
keys.unshift(k);
}
for (var c = keys.length, n = 0; n < c; n++) {
alert(arr[keys[n]]);
}
For a normal array, I would have done this:
var i = arr.length;
while (i--) {
var value = arr[i];
alert(i =") "+ value);
}
This is faster than a "for" loop.
http://blogs.oracle.com/greimer/entry/best_way_to_code_a
In modern browsers you can now use Object.keys to get your array of properties and step through it in reverse order, allowing you to skip the preliminary key collection loop.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
var keys = Object.keys(subject);
for (var i = keys.length-1; i >= 0; i--) {
var k = keys[i],
v = subject[k];
console.log(k+":",v);
}

Categories

Resources