Can't reference array by index - javascript

I have an array defined as:
var subjectCache = [];
I then have some code to build it up, which is working ok.
However, if I try to reference the array by an index, e.g.:
var x = subjectCache[0];
or
var x = subjectCache[1];
I get undefined.
Also subjectCache.length is always 0 (zero).
if I try to reference it by its key, e.g.:
var x = subjectCache['12345'];
it works.
Is this normal? Shouldn't I be able to reference it by its index whatever?
I'm using Internet Explorer, if it makes a difference (and it probably does :( )
[Edit]
this is the code I'm using to build the array, although I really don't think it is to blame.
It's a callback from a webservice call. This is working fine and the array is being populated.
var subjectCache = [];
var subjectCacheCount = 0;
function refreshSubjectsCallback(data) {
// update subjects
// loop through retrieved subjects and add to cache
for( i=0; i < data.length; i++ )
{
var subject = data[i];
var subjectid = subject.SubjectId;
subjectCache[subjectid] = subject;
subjectCacheCount += 1;
}
}
[/Edit]

You're probably assigning keys manually instead of using subjectCache.push() to add new elements to the array:
var array = [];
array['foo'] = 'bar';
console.log(array.length); // 0
The length attribute isn't going to reflect those changes the way you'd expect:
> var a = [];
undefined
> a[100] = 2; // The previous `100` entries evaluate to `undefined`
2
> a.length;
101
Instead, use an object:
var object = {};
object['foo'] = 'bar';
for (var key in object) {
var value = object[key];
console.log(value);
}

From your symptoms, it sounds like you are trying to treat the array as an associative array.
In Javascript, arrays work like this:
var a = [];
a[1] = 10;
alert(a.length);
Objects work like this:
var o = {};
o.myProp = true;
o["myOtherProp"] = false;

Arrays only work with numeric keys not strings. Strings assign properties to the object, and aren't counted as part of length nor it's numeric indices.
When building the array, make sure you are assigning to a numeric position within the array.

No, it will not work, because you haven't created arrays but objects.
you will have to access it by its key.
var x = subjectCache['12345'];
If this works and subjectCache.length doesn't, I think you are making an object not an array. You are confused.

Somewhere along the road you lost the array, and the variable subjectCache points to a different kind of object.
If it was an array, it can't have the length zero and contain an item that is reachable using subjectCache['12345']. When you access an item in an array it doesn't make any difference if you use a numeric index or a string representing a number.

Related

Creating many random arrays for use as elements in another array

Consider:
var main = []
Now I want to generate many (289 to be exact) Arrays to be elements in the main one. Each of these arrays will have be like:
var subobject = {x:"A", y:"B", terrain:"C", note:"D"}
Generating the values are no problem, and I can easily put those values in a already defined subobject = {} and push(), but I can't figure out how to iterate a script each time which creates a new object and then push() into var main.
The naming of the subobject is unimportant, I'm looking for solution inwhich I can pull specific information such as:
main[0].x // get x value of the subarray in 0 location in main
main[5].note// get note value of the subarray in 5 location in main
(would it make a difference if every array had the same name? since I would never access subobject directly (after being pushed into main), but through main[X].YYY or would it have to be via main[X].subarray[Y] ?)
for (var i = 0; i < 289; i++) {
main.push({x: getRandomX(), y: getRandomY(), terrain: getTerrain(), note: ""});
}
as long as you create new objects {} before you push them to the array it is ok.
it doesn't matter if you assign the new object to the same variable (ie subobject)
you access them later like this:
main[0].x // get the value of x of the first element
[x:"A", y:"B", terrain:"C", note:"D"] isn't valid javascript, I think you want an object here:
{x:"A", y:"B", terrain:"C", note:"D"}
And to push each generated value, you can use a for loop
for (var i = 0; i < 9; i++) {
//do something, for example, generate a value
}
Arrays are only numerically indexed.
If you want named keys you have to use objects.
Here's the wrong way to do it.
var main = [],
subobject = {x:"A", y:"B", terrain:"C", note:"D"};
for(var i=0; i<289; i++){
subobject["x"] = Math.random();
subobject["terrain"] = Math.random();
//continue adding values using keys
main.push(subobject);
}
The thing is if you just use the same object your going to access that object every time you iterate it, and you'll replace it's value.
So you should do it like this.
var main = [],
subobject = {};
for(var i=0; i<289; i++){
subobject = {};//new object to make for uniquness
subobject["x"] = Math.random();
subobject["terrain"] = Math.random();
//continue adding values using keys
main.push(subobject);
}
You access members like this.
main[0].x;//value of x at index 0
//next index
main[1].terrain;//value of terrain at index 1
Collisions will only happen if you set the same index twice.
main[2].x = "value";
main[2].x = "replace value by accident";
Unless you want to change the value for some reason.
A different index will always give you a different object if you set a different one each time.

Get the length of an array within a JSON object

I want to find out how many items are in my JSON object. I have seen many answers but they all deal with a common value to loop through. I am wanting the results to tell me that there are 2 items in this object. Any help would be great!
[{"manager_first_name":"jim","manager_last_name":"gaffigan"}]
You could use Object.keys in newer browsers. It would return an array of all the keys in the object, and that array would have a length property that will tell you how many items there are in the object :
var arr = [{"manager_first_name":"jim","manager_last_name":"gaffigan"}];
var length = Object.keys(arr[0]).length;
FIDDLE
In non-supporting browsers, you have to iterate
var arr = [{"manager_first_name":"jim","manager_last_name":"gaffigan"}];
var i = 0;
for (var key in arr[0]) i++;
FIDDLE
You can do this:
var arr = [{"manager_first_name":"jim","manager_last_name":"gaffigan"}],
length = 0,
obj = arr[0]; // Get first obj from array
for(var k in obj){
if( obj.hasOwnProperty(k) ) {
length++;
}
}
console.log(length); // Shows 2
You should use hasOwnProperty because you can also extend an Object with functions, there could otherwise also be count als keys.
Links:
hasOwnProperty
Try
var jsonArr = [{"manager_first_name":"jim","manager_last_name":"gaffigan"}];
var itemCount = JSON.stringify(jsonArr).split('":"').length - 1;
This is, of course, a rather coarse(and unreliable) way of doing it, but if you just want the item count, this should work like a charm.

how to generate arrays automatically in javascript?

I want to make a loop that makes arrays automatically and assign the values to it.
The problem is how to generate the array itself automatically.
for(var attGetter=1; attGetter <= num; attGetter++){
var catesArray1 = new Array();
for(var atttGetterArray=1; atttGetterArray <= series; attGetterArray++){
idOfInput = "cate"+chartGetter+"_series"+attGetterArray;
catesArray1.push($("#"+idOfInput).val());
}
}
I want the loop to generate the array itself automatically like
catesArray1
catesArray2
catesArray3
and so on..
You need an object or an array to hold the multiple arrays you wish to create. Maybe something you are looking for is like the following?
var arrayHolder = new Array();
for(var attGetter=1; attGetter <= num; attGetter++){
var catesArray = new Array();
for(var attGetterArray=1; atttGetterArray <= series; attGetterArray++){
idOfInput = "cate"+chartGetter+"_series"+attGetterArray;
catesArray.push($("#"+idOfInput).val());
}
arrayHolder.push(catesArray);
}
If you want the arrays to be in global namespace, You can try
window['catesArray' + attGetter] = [];
...
window['catesArray' + attGetter].push(...)
Else you can create a hash object and use it to hold the reference
var obj = {};
.....
obj['catesArray' + attGetter] = [];
.....
obj['catesArray' + attGetter].push(...)
In that case you will have to create one new array that holds all the cacatesArrays from first for loop
var catesArrayContainer = new Array(); //<<<---------------------
for(var attGetter=1; attGetter <= num; attGetter++){
var catesArray = new Array();
for(var atttGetterArray=1; atttGetterArray <= series; attGetterArray++){
idOfInput = "cate"+chartGetter+"_series"+attGetterArray;
catesArray.push($("#"+idOfInput).val());
}
catesArrayContainer.push(catesArray); //<<<--------------------
}
EDIT :
This happens because the scope of variable catesArray1 was limited. When the loop enters next iteration the catesArray1 gets reinitialized, thus losing all the previously stored values...
Now in the code I have posted, we are storing every instance of catesArray1 in another array, and your values persist out side of the for loop
You can do something like this for 4 arrays of 5 elements each
yourarray=[];
for (i = 0; i <4; i++) {
temparray=[];
for (j = 0; j < 5; j++) {
temparray.push($('#'+whateverID+'_'+i+'_'+j)) //your values here
}
yourarray.push(temparray);
}
Check it on this JSFiddle. open chrome console to see array
If you want to create array within loop from index
You can use eval to evaluate javascript from strings but i wont use that unless there is no other way. you can see both above and eval method in this Fiddle. Open Chrome console to see array values
Just a comparison of using eval and 2D array
Open console in chrome while you run this jsFiddle and you will see the difference in eval and 2darray in context of this question.
You should assign them to an object. In this case, make an object variable before the first for-loop to hold all arrays:
var allArrays = {};
for(var attGetter=1; attGetter <= num; attGetter++){
var currentArray = allArrays['catesArray' + attGetter] = new Array();
for(var atttGetterArray=1; atttGetterArray <= series; attGetterArray++){
idOfInput = "cate"+chartGetter+"_series"+attGetterArray;
currentArray.push($("#"+idOfInput).val());
}
}
Instead of attempting to create & allocate dynamically named variables, I would think of this more of an array of array's if you will. In other words, create an array that holds all of the arrays you want:
var collections = []; // Literal notation for creating an array in JS
From here, it's a matter of making each value you create within this array its own array:
var n = 10; // Total amount of arrays you want
for (var i = 0; i < n; i++) {
var values = [];
// Have another loop that fills in the values array as expected
collections.push(values); // Each element at collections[i] is its own array.
}
If you truly need named elements, you could potentially do something very similar with just an object {} instead, and refer to each element by a name you create.
var collections = {}; // Literal notation for an object in JS
var n = 10; // Total amount of arrays you want
for (var i = 0; i < n; i++) {
var values = []; // Literal notation for an array in JS
// Fill in the values array as desired
var name = 'arr' + i; // How you'll refer to it in the object
collections[name] = values;
}
I suggest the former though, since it does not sound like you need to have explicit names on your arrays, but just want multiple layers of arrays.

Getting Length of Object in Javascript / jQuery

I am trying to set up an array in jQuery and I then need to do a for loop on it. But it seems that I cant use an associative array for some reason?
var items = new Array();
items['foo'] = 123456;
items['bar'] = 789012;
items['baz'] = 345678;
items['bat'] = 901234;
alert(items.length);
This is just a test, but it return 0?
You can't make associative array in JavaScript like what you want, instead you can use Object.
For example:
var items = {
foo : 123456,
bar : 789012,
baz : 345678,
bat : 901234
}
And to calculate the length you can do:
var getObjectSize = function(obj) {
var len = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) len++;
}
return len;
};
Use: getObjectSize(items); // output: 4
For more see here.
Another one is:
Object.keys(items).length;
But not supported by all browsers.
var items = new Array();
items['foo'] = 123456;
The problem lies in the very first line. You believe that you are adding an item to the array at the index foo, but you are actually adding a property to the items variable with a key foo and value 123456. If you were to type items.foo it would give you back your 123456.
The problem with this approach is that adding a property to an array does not magically increase it's length.
If you want to have non-numeric indexes, you need to use an object instead of an array:
var items = {
foo: 123456,
bar: 789012,
baz: 345678,
bat: 901234
};
Another approach might be to set up two different arrays, which you construct in parallel:
var items = [], items2 = [];
items.push('foo');
items2.push(123456);
// etc.
alert(items2.length);​
The efficiency of this approach depends on how you'll use it. If you're only going to loop through the list of items and do something to each of them, this approach may be more efficient. But if you need to use it like an associative array (items['foo']), then you're better off building an object.
The .length property returns the highest numerical index of the array. Thus, in your case, there is no numerical index and it returns 0. Try
items[98] = "something";
items.length will be 98..! Use the .length property with caution, and if you also want to count the non-numerical indici, loop over the Object (an Array is also an Object) and count its ownProperties.

Javascript putting values in two-dimensional array

Is there a better way to create a two-dimensional array in javascript than this?
var divcookies = new Array();
divcookies[0] = new Array(2);
divcookies[0][0] = name;
divcookies[0][1] = value;
This results in a two dimensional array with bad data added in the middle of it. I expect an array like this.
(name1, value1, name2, value2, name3, value3)
Instead I get this.
(name1, value2, ,name2, value2, name3, value3)
I don't really know when that extra bad data is added because if I alert during the loop that fills the array it only seems to loop through 3 times to put the three pairs of values expected.
So I am looking for a different way to get the two dimensional array.
function get_cookies_array() {
var divcookies = new Array();
if (document.cookie && document.cookie != '') {
var split = document.cookie.split(';');
for (var i = 0; i < split.length; i++) {
var name_value = split[i].split("=");
name_value[0] = name_value[0].replace(/^ /, '');
if ( name_value[0].search("compage") != -1 ) {
alert (divname+" "+ divarray);
divcookies[i] = new Array(2);
divcookies[i][0] = decodeURIComponent(name_value[0]);
divcookies[i][1] = decodeURIComponent(name_value[1]);
}
}
}
alert (divcookies);
return divcookies;
}
jsBin http://jsbin.com/iwuqab
The recommended method for creating arrays in JS is to NOT use the 'new' method. Instead, do:
var divcookies = [];
divcookies[0] = [];
divcookies[0][0] = name;
divcookies[0][1] = value;
This notation frees you up from having to specify element numbers in advance. Once a variable's been initialized as an array, you can set any index you want. The downside (regardless of which notation you use) is that you have to initialize every sub-array as well.
Your 2-dimensional array is set up correctly (well, [] is preferred instead of new Array()). The actual problem is only with the display of your array using alert(divcookies). Here, divcookies is converted to a string using the predefined method toString(). This method creates a list of comma-separated array elements, from the first element to the last element. If some elements in between are not set, an empty string is output. In your case, you are not assigning to those indexes i of divcookies for which name_value[0].search("compage") == -1. These are the gaps ,, in the alerted list.

Categories

Resources