123

When I create a new JavaScript array, and use an integer as a key, each element of that array up to the integer is created as undefined.

For example:

var test = new Array();
test[2300] = 'Some string';
console.log(test);

will output 2298 undefined's and one 'Some string'.

How should I get JavaScript to use 2300 as a string instead of an integer, or how should I keep it from instantiating 2299 empty indices?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131

11 Answers11

145

Use an object, as people are saying. However, note that you can not have integer keys. JavaScript will convert the integer to a string. The following outputs 20, not undefined:

var test = {}
test[2300] = 20;
console.log(test["2300"]);
Saeed
  • 5,413
  • 3
  • 26
  • 40
Claudiu
  • 224,032
  • 165
  • 485
  • 680
  • 13
    +1 Note that this is even true of Arrays! see http://stackoverflow.com/questions/1450957/pythons-json-module-converts-int-dictionary-keys-to-strings#1450981 – bobince Jan 04 '10 at 23:38
  • 1
    @bobince: Internally, sure. However, _logically_, arrays have integer "keys". – Lightness Races in Orbit Nov 17 '12 at 22:53
  • 2
    Please note, that using integer as key will change the length of your array. You should definitely use Object instead. I just wanted to use facebook id as the key, and JSON.stringify would crash my machine ;) – Krystian Dec 04 '13 at 15:50
  • 3
    @LightnessRacesinOrbit The internal details can still leak out and bite you though. See this simplified version of what I ran into today: http://jsfiddle.net/cincodenada/pseujLex/2/ It may seem contrived when reduced, but was a sensical part of a larger script (and is a bit less contrived in CoffeeScript: http://jsfiddle.net/cincodenada/oojr7Ltn/2/). This seeming implementation detail cost me a good bit of bug-hunting today. – cincodenada Aug 22 '14 at 19:43
  • @cincodenada: You're going to have to present a screenshot because there's nothing unusual about the result of that fiddle in my browser. I'd wager you're referring to the issues I explore in http://kera.name/articles/2011/09/a-brief-introduction-to-javascript-objects-arrays/. – Lightness Races in Orbit Aug 23 '14 at 14:13
  • 1
    I've [updated the fiddle](http://jsfiddle.net/cincodenada/pseujLex/5/) to make the issue clearer. [Here](http://i.imgur.com/W3oHaI6.png) is what I see in recent FF and Chrome. Note that the [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in), for instance, only cautions that order is not guaranteed using `for..in` with Arrays, with no mention of the keys not being integers, and even implies that they *will* be integers. I don't disagree that using Array.forEach is generally a better solution, but the internals *can* leak out. – cincodenada Aug 23 '14 at 22:28
  • Also worth noting that dot notation doesn't work when object keys are integers. test = {"20": "a", "B": "b"}. Now try to access test.B and test.20 – Julian Mann May 14 '15 at 18:18
  • 2
    A little note for non-whole numbers: `0.25` and `.25` resolve to the same string `"0.25"`. So if you're using fractional keys, you can retrieve the property of a numerically set key `0.25` using `0.25`, `.25`, `"0.25"` but not `".25"`. – Sandy Gifford Sep 08 '15 at 20:39
  • @Claudiu there is no way to prove whether "numeric-looking" keys are stored internally as integers or strings. `for (var key in a) { console.log(typeof a); }` will print `string` even for keys of arrays. It could be that even array keys are stored internally as strings, and that a[103] is coercing `103` into a string, even though that would be ludicrous. – Andy Jan 07 '16 at 15:02
  • However, considering that "numeric" object keys come first in `for..in` in most modern JS engines, I assume that they store them internally as numbers and `a["103"]` is coercing `"103"` into a number. – Andy Jan 07 '16 at 15:04
  • What about special characters as keys for instance '{' key with the value '}'. ? – eran otzap Dec 13 '16 at 20:15
  • The statement is not generally true. If you try `var a = {}; a[100000000000000000000000000000] = true; console.log(a["100000000000000000000000000000"]); console.log(a[100000000000000000000000000000]);` you will be surprised that only the second log gives `true`. As you know, javascript has a hard time with big numbers and calculation. – victor175 Aug 13 '19 at 11:37
37

You can just use an object:

var test = {}
test[2300] = 'Some string';
Annie
  • 6,621
  • 22
  • 27
25

As people say, JavaScript will convert a string of number to integer, so it is not possible to use directly on an associative array, but objects will work for you in similar way I think.

You can create your object:

var object = {};

And add the values as array works:

object[1] = value;
object[2] = value;

This will give you:

{
  '1': value,
  '2': value
}

After that you can access it like an array in other languages getting the key:

for(key in object)
{
   value = object[key] ;
}

I have tested and works.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jesuslg123
  • 726
  • 6
  • 16
22

If the use case is storing data in a collection then ECMAScript 6 provides the Map type.

It's only heavier to initialize.

Here is an example:

const map = new Map();
map.set(1, "One");
map.set(2, "Two");
map.set(3, "Three");

console.log("=== With Map ===");

for (const [key, value] of map) {
    console.log(`${key}: ${value} (${typeof(key)})`);
}

console.log("=== With Object ===");

const fakeMap = {
    1: "One",
    2: "Two",
    3: "Three"
};

for (const key in fakeMap) {
    console.log(`${key}: ${fakeMap[key]} (${typeof(key)})`);
}

Result:

=== With Map ===
1: One (number)
2: Two (number)
3: Three (number)
=== With Object ===
1: One (string)
2: Two (string)
3: Three (string)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Pragmateek
  • 13,174
  • 9
  • 74
  • 108
12

Compiling other answers:

Object

var test = {};

When using a number as a new property's key, the number turns into a string:

test[2300] = 'Some string';
console.log(test['2300']);
// Output: 'Some string'

When accessing the property's value using the same number, the number is turned into a string again:

console.log(test[2300]);
// Output: 'Some string'

When getting the keys from the object, though, they aren't going to be turned back into numbers:

for (var key in test) {
    console.log(typeof key);
}
// Output: 'string'

Map

ECMAScript 6 allows the use of the Map object (documentation, a comparison with Object). If your code is meant to be interpreted locally or the ECMAScript 6 compatibility table looks green enough for your purposes, consider using a Map:

var test = new Map();
test.set(2300, 'Some string');
console.log(test.get(2300));
// Output: 'Some string'

No type conversion is performed, for better and for worse:

console.log(test.get('2300'));
// Output: undefined
test.set('2300', 'Very different string');
console.log(test.get(2300));
// Output: 'Some string'
wordbug
  • 641
  • 5
  • 10
4

Use an object instead of an array. Arrays in JavaScript are not associative arrays. They are objects with magic associated with any properties whose names look like integers. That magic is not what you want if you're not using them as a traditional array-like structure.

var test = {};
test[2300] = 'some string';
console.log(test);
bdukes
  • 152,002
  • 23
  • 148
  • 175
  • 1
    They *can* be associative arrays, but only because they are also objects which can have named properties set. But this just makes things ridiculously confusing, and so yes, objects are much better to use. – Graza Jan 04 '10 at 23:08
  • Arrays can never be associative Graza. If you try to use keys in an array and then iterate over them you'll notice you're also iterating through all the default methods and properties of arrays -> not very desirable. – Swizec Teller Jan 04 '10 at 23:11
  • @Swizec - exactly why I said "ridiculously confusing". You *can* use an array as an associative array - that is as name/value pairs, but you would never want to iterate them! (I was simply pointing out a technicality, definitely not something I would at all recommend doing) – Graza Jan 04 '10 at 23:28
  • yes, but when iterating they're not in any particular order (i.e. order is not guaranteed), which would be the point of numbering them, so it's a lot worse than just confusing. – Julix Jan 03 '17 at 05:43
3

Try using an Object, not an Array:

var test = new Object(); test[2300] = 'Some string';
Jeff Hammerbacher
  • 4,226
  • 2
  • 29
  • 36
  • 3
    This is definitely the way to go. This way you won't create 2300 entries long array in order to store a single string. – Krystian Dec 04 '13 at 15:50
  • 2
    @Krystian JS arrays are fake arrays. Run `var a = []; a[Math.pow(2, 30)] = 'hello';` and you won't see the browser/memory usage shoot up by over a gigabyte, but you will see `a.length` is 1073741824. VMs clearly store some "arrays" using some other data structure, I'm guessing simply a hashtable, at least if they're sufficiently sparse. – Andy Jan 07 '16 at 15:10
2

Get the value for an associative array property when the property name is an integer:

Starting with an associative array where the property names are integers:

var categories = [
    {"1": "Category 1"},
    {"2": "Category 2"},
    {"3": "Category 3"},
    {"4": "Category 4"}
];

Push items to the array:

categories.push({"2300": "Category 2300"});
categories.push({"2301": "Category 2301"});

Loop through the array and do something with the property value.

for (var i = 0; i < categories.length; i++) {
    for (var categoryid in categories[i]) {
        var category = categories[i][categoryid];
        // Log progress to the console
        console.log(categoryid + ": " + category);
        //  ... do something
    }
}

Console output should look like this:

1: Category 1
2: Category 2
3: Category 3
4: Category 4
2300: Category 2300
2301: Category 2301

As you can see, you can get around the associative array limitation and have a property name be an integer.

NOTE: The associative array in my example is the JSON content you would have if you serialized a Dictionary<string, string>[] object.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jason Williams
  • 2,740
  • 28
  • 36
1

Simple solution if you would rather use an array. When adding the number just preface it with a letter.

e.g.

let ctr = 3800;
let myArray=[];
myArray["x" + ctr.toString()]="something";
myArray["x" + (ctr+1).toString()]="another thing";

Then just add the "x" in access routines that call the number as an index. e.g.: console.log( myArray["x3800"] ); or: console.log( myArray["x"+ numberOfYourChoice.toString()] );

malac usp
  • 31
  • 2
0

Use an object - with an integer as the key - rather than an array.

Upperstage
  • 3,747
  • 8
  • 44
  • 67
0

Sometimes I use a prefixes for my keys. For example:

var pre = 'foo',
    key = pre + 1234

obj = {};

obj[key] = val;

Now you don't have any problem accessing them.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
pictus
  • 77
  • 1
  • 6