Is array both associative and indexed?
Solution 1
There are no such things as associative arrays in Javascript. You can use object literals, which look like associative arrays, but they have unordered properties. Regular Javascript arrays are based on integer indexes, and can't be associative.
For example, with this object:
var params = {
foo: 1,
bar: 0,
other: 2
};
You can access properties from the object, for example:
params["foo"];
And you can also iterate over the object using the for...in
statement:
for(var v in params) {
//v is equal to the currently iterated property
}
However, there is no strict rule on the order of property iteration - two iterations of your object literal could return the properties in different orders.
Solution 2
After reading the Wikipedia definition of associative array, I'm going to break with traditional JavaScript lore and say, "yes, JavaScript does have associative arrays." With JavaScript arrays, you can add, reassign, remove, and lookup values by their keys (and the keys can be quoted strings), which is what Wikipedia says associative arrays should be able to do.
However, you seem to be asking something different--whether you can look up the same value by either index or key. That's not a requirement of associative arrays (see the Wikipedia article.) Associative arrays don't have to give you the ability to get a value by index.
JavaScript arrays are very closely akin to JavaScript objects.
arr=[];
arr[0]="zero";
arr[1]="one";
arr[2]="two";
arr["fancy"]="what?";
Yes, that's an array, and yes, you can get away with non-numeric indices. (If you're curious, after all this, arr.length is 3.)
In most cases, I think you should stick to numeric indices when you use arrays. That what most programmers expect, I think.
The link is to my blog post about the subject.
Solution 3
Native JS objects only accept strings as property names, which is true even for numeric array indices; arrays differ from vanilla objects only insofar as most JS implementations will store numerically indexed properties differently (ie in an actual array as long as they are dense) and setting them will trigger additional operations (eg adjustment of the length
property).
If you're looking for a map which accepts arbitrary keys, you'll have to use a non-native implementation. The script is intended for fast iteration and not random-access by numeric indices, so it might nor be what you're looking for.
A barebones implementation of a map which would do what you're asking for could look like this:
function Map() {
this.length = 0;
this.store = {};
}
Map.prototype.get = function(key) {
return this.store.hasOwnProperty(key) ?
this.store[key] : undefined;
};
Map.prototype.put = function(key, value, index) {
if(arguments.length < 3) {
if(this.store.hasOwnProperty(key)) {
this.store[key].value = value;
return this;
}
index = this.length;
}
else if(index >>> 0 !== index || index >= 0xffffffff)
throw new Error('illegal index argument');
if(index >= this.length)
this.length = index + 1;
this[index] = this.store[key] =
{ index : index, key : key, value : value };
return this;
};
The index
argument of put()
is optional.
You can access the values in a map map
either by key or index via
map.get('key').value
map[2].value
Solution 4
var myArray = Array();
myArray["first"] = "Object1";
myArray["second"] = "Object2";
myArray["third"] = "Object3";
Object.keys(myArray); // returns ["first", "second", "third"]
Object.keys(myArray).length; // returns 3
if you want the first element then you can use it like so:
myArray[Object.keys(myArray)[0]]; // returns "Object1"
Solution 5
The order in which objects appear in an associative javascript array is not defined, and will differ across different implementations. For that reason you can't really count on a given associative key to always be at the same index.
EDIT:
as Perspx points out, there aren't really true associative arrays in javascript. The statement foo["bar"]
is just syntactic sugar for foo.bar
If you trust the browser to maintain the order of elements in an object, you could write a function
function valueForIndex(obj, index) {
var i = 0;
for (var key in obj) {
if (i++ == index)
return obj[key];
}
}
Comments
-
puffpio almost 2 years
Can an array in JavaScript be associative AND indexed?
I'd like to be able to lookup an item in the array by its position or a key value.
-
Paolo Bergantino almost 15 yearsAlthough this is a true, in practice all major browsers loop over the properties of an object in the order in which they were defined. This is not in the spec, of course, but it's worth a mention.
-
Nosredna almost 15 yearsActually, JavaScript arrays can have non-integer indices as well. It just doesn't have much in the way of methods for dealing with them.
-
user5880801 almost 15 yearsYou were right when you said "And you can have an array with non-numeric indices". It slipped my mind somehow, but I know this fact.
-
BaroqueBobcat almost 15 yearsTo be pedantic, "fancy" is not an index in the array, but an attribute of the array instance object.
-
roryf almost 15 yearsYou mean like a string? in that case it isn't an array, just an object with properties.
-
Nosredna almost 15 yearsYeah, good point. That's why I say that arrays are closely related to objects in JavaScript.
-
linusthe3rd almost 15 yearsNosredna: JS arrays do not have key indices, those JS objects are considered object literals. so: foo["bar"] = 1; foo.bar === foo["bar"]; //true foo["bar"] === foo[0]; //false This is one of the many subtle quirks about JS that throw people off easily.
-
Miles almost 15 years+1, but I would lose "numerically indexed properties will be stored differently": that's not necessarily the case, and isn't required by the spec.
-
Miles almost 15 years@BaroqueBobcat: to be really pedantic :) indices in the array are just properties ("attributes") of the array instance object; an array just treats specially those properties which are the string form of an integer with regards to the length property.
-
puffpio almost 15 yearsbut then stuff.length would not be 1 anymore since you added .bar right? thus looping through by index wouldnt really work anymore..
-
NickFitz almost 15 yearsNo - adding a named property doesn't increase the length; only adding an element by numeric index increases length. Adding "stuff[1000] = 'blah'" would cause the length to increase to 1001, even though only two numerically-indexed elements and one named property have actually been added. Fun isn't it ;-)
-
Amit Patil about 14 yearsJavaScript Objects, including Arrays, have only string indices.
a[1]
is actually sayinga['1']
. -
Chris over 13 yearsHow do you put? map.put('key','value') and map[2].value = val ?
-
Christoph over 13 years
map.put('key','value')
for appending a value andmap.put('key','value', 42)
for inserting a value at a given position;map[42].value = 'value'
will also work (ie replace the value of an existing key-value-pair), but you can't change the key or index of the entry or add new entries this way -
Lightness Races in Orbit almost 13 yearsIt's not pedantic at all. It's an incredibly important distinction, made evident when you start trying to serialise your array into, say, JSON. The value with a non-numeric key is not part of the array data. (And strictly speaking, you're breaking your array by not using
.push()
.) -
Ryan about 12 yearsOh and if you are going to do this in a loop you will likely need closures btw... just saying.
-
kontur over 11 yearsI downvoted this answer, because while it might be possible to use syntaxt that looks like an array, this is not proper javascript nor a proper array. Your answer is good for reference, but should have a clear reminder that this is NOT how you'd conventionally use arrays.
-
z.a. over 8 yearsArrays should be able to be indexed so when it's iterated, it is returned in order, but here it's not the case.
-
Daniel Sokolowski about 6 yearsThis is the approach I took, but with a syntax showing the association at assignment which I found more to my liking
aSignals[aSignals.length] = aSignals['fooBar'] = { 'sKey': 'foobBar', ... }
-
gujralam over 3 yearsThe latest MDN documentation makes it quiet clear that Array index must be integers. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
-
Scott Marcus over 3 yearsJavaScript does not have associative arrays. Your answer is talking about objects, not arrays.
-
Scott Marcus over 3 yearsI know this is an old post, but to be clear, JavaScript does not have associative arrays and you cannot pass a string index to an array. What you are talking about here is an object with keys.