Використання цілого числа як ключа в асоціативному масиві JavaScript


102

Коли я створюю новий масив JavaScript і використовую ціле число в якості ключа, кожен елемент цього масиву до цілого числа створюється як невизначений.

Наприклад:

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

виведе 2298 невизначених та один 'Some string'.

Як я можу змусити JavaScript використовувати 2300 як рядок замість цілого чи, або як я можу не захищати 2299 порожніх індексів?

Відповіді:


128

Використовуйте об'єкт, як кажуть люди. Однак зауважте, що у вас не може бути цілих ключів. JavaScript перетворить ціле число в рядок . Наступні виводи 20, не визначені:

var test = {}
test[2300] = 20;
console.log(test["2300"]);

12
+1 Зауважте, що це стосується навіть масивів! см stackoverflow.com/questions/1450957 / ...
bobince

1
@bobince: Всередині, звичайно. Однак, логічно , масиви мають цілі "ключі".
Гонки легкості по орбіті

1
Зауважте, що використання цілого числа як ключа змінить довжину масиву. Ви повинні обов'язково використовувати Object замість цього. Я просто хотів використовувати ідентифікатор facebook як ключ, і JSON.stringify зірве мою машину;)
Кристян

2
@LightnessRacesinOrbit Внутрішні деталі все ще можуть просочитися і покусати вас. Дивіться цю спрощену версію того, на що я зіткнувся сьогодні: jsfiddle.net/cincodenada/pseujLex/2 Це може здатися надуманим при зменшенні, але було чуттєвою частиною більшого сценарію (і трохи менше надуманого в CoffeeScript: jsfiddle.net/ cincodenada / oojr7Ltn / 2 ). Ця начебто детальна реалізація сьогодні коштувала мені непоганого полювання на помилок.
cincodenada

1
Маленька примітка для нецілих чисел: 0.25і .25дозволити до того ж рядка "0.25". Так що якщо ви використовуєте дробові ключі, ви можете отримати властивість чисельно встановити ключ , 0.25використовуючи 0.25, .25, "0.25"але не ".25".
Сенді Гіффорд

34

Ви можете просто використовувати об’єкт:

var test = {}
test[2300] = 'Some string';

16
І все-таки виходить на рядок.
намальовано010

1
@ drew010 так, об’єкти Javascript дозволяють індексувати лише рядки.
Пітікос

22

Як кажуть люди, JavaScript перетворить рядок числа в ціле число, тому використовувати його безпосередньо в асоціативному масиві неможливо, але об'єкти будуть працювати для вас аналогічно, як я думаю.

Ви можете створити свій об’єкт:

var object = {};

І додайте значення, як працює масив:

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

Це дасть вам:

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

Після цього ви можете отримати доступ до нього як до масиву іншими мовами, отримавши ключ:

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

Я перевірив і працює.


17

Якщо випадок використання зберігає дані в колекції, то тип ECMAScript 6 надає Mapтип.

Ініціалізувати лише важче.

Ось приклад:

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)})`);
}

Результат:

=== With Map ===
1: One (number)
2: Two (number)
3: Three (number)
=== With Object ===
1: One (string)
2: Two (string)
3: Three (string)

11

Складання інших відповідей:

Об'єкт

var test = {};

Використовуючи число як ключ нового властивості, число перетворюється на рядок:

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

При доступі до значення властивості з використанням того ж числа, це число знову перетворюється на рядок:

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

Однак, отримуючи ключі від об'єкта, вони не збираються повертатись назад у цифри:

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

Карта

ECMAScript 6 дозволяє використовувати об’єкт Map ( документація , порівняння з Object ). Якщо ваш код призначений для інтерпретації локально або таблиця сумісності ECMAScript 6 виглядає досить зеленою для ваших цілей, спробуйте скористатися картою:

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

Перетворення типів не проводиться для кращого та гіршого:

console.log(test.get('2300'));
// Output: undefined
test.set('2300', 'Very different string');
console.log(test.get(2300));
// Output: 'Some string'

4

Використовуйте об'єкт замість масиву. Масиви в JavaScript не є асоціативними масивами. Вони є предметами з магією, пов'язаними з будь-якими властивостями, назви яких мають вигляд цілих чисел. Ця магія - це не те, чого ви хочете, якщо ви не використовуєте їх як традиційну структуру, схожу на масив.

var test = {};
test[2300] = 'some string';
console.log(test);

1
Вони можуть бути асоціативними масивами, але лише тому, що вони також є об'єктами, які можуть мати набір властивостей. Але це просто робить речі смішно заплутаними, і так так, об'єкти набагато краще використовувати.
Граца

Масиви ніколи не можуть бути асоціативними Graza. Якщо ви спробуєте використовувати ключі в масиві, а потім повторити їх, ви помітите, що ви також повторюєте всі методи за замовчуванням і властивості масивів -> не дуже бажано.
Swizec Teller

@Swizec - саме тому я сказав "смішно заплутаним". Ви можете використовувати масив як асоціативний масив - це як імена / значення пар, але ви ніколи не хочете їх повторювати! (Я просто вказував на технічність, напевно, це не те, що я б взагалі рекомендував робити)
Graza

так, але при повторенні вони не в якомусь конкретному порядку (тобто порядок не гарантується), що було б сенсом їх нумерації, тому це набагато гірше, ніж просто плутати.
Джулікс

3

Спробуйте використовувати об’єкт, а не масив:

var test = new Object(); test[2300] = 'Some string';

3
Це, безумовно, шлях. Таким чином ви не створите 2300 довгих масивів для зберігання однієї рядка.
Кристян

2
@Krystian JS-масиви - це підроблені масиви. Запустіть, var a = []; a[Math.pow(2, 30)] = 'hello';і ви не побачите зйомку браузера / використання пам'яті понад гігабайт, але ви побачите, що a.lengthце 1073741824. Відеомагнітофони чітко зберігають деякі "масиви", використовуючи якусь іншу структуру даних, я гадаю, просто хешбел, принаймні, якщо вони досить рідкі.
Енді

2

Отримайте значення для властивості асоціативного масиву, коли ім'я властивості є цілим числом:

Починаючи з асоціативного масиву, де імена властивостей є цілими числами:

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

Натисніть на елементи до масиву:

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

Проведіть цикл через масив і зробіть щось зі значенням властивості.

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
    }
}

Вихід консолі повинен виглядати так:

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

Як бачимо, ви можете обійти обмеження асоціативного масиву та мати властивість імені бути цілим числом.

ПРИМІТКА. Асоціативний масив у моєму прикладі - це вміст JSON, який ви мали б, якби ви серіалізували об'єкт Словник <рядок, рядок> [].



0

Іноді я використовую префікси для своїх ключів. Наприклад:

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

obj = {};

obj[key] = val;

Тепер у вас немає проблем із доступом до них.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.