Форсирование строкового представления ключа массива - PullRequest
0 голосов
/ 29 февраля 2020

Я пытаюсь поддерживать порядок массива со смешанными типами ключей. Массив содержит в основном ключи, представленные строковыми значениями, но если вы введете пронумерованный ключ, он уходит вперед. Как я могу заставить ключ, который является числом, быть строковым типом?

Например,

array = [];
array["one"] = "some data";
array["two"] = "some more data";
array["3"] = "this should not be the first element";

Как я могу сделать "3" строковым типом, чтобы предотвратить его перемещение наверх индекса?

Ответы [ 3 ]

2 голосов
/ 29 февраля 2020

Ух ты когда-нибудь открывал несколько банок червей.

Javascript Массивы - это особый тип Javascript объектов, и, как и у всех Javascript объектов, они могут иметь произвольные строковые свойства:

const foo = [];
foo["bar"] = "hi";

Однако эта строка является свойством объекта массива, а не элементом в массиве:

foo.forEach(console.log); // logs nothing

Вы по-прежнему можете обращаться к нему, как и к любому другому свойству объекта:

console.log(foo["bar"]); // "hi"

Но он не будет отображаться в обычных итеративных конструкциях, таких как c -стиль для циклов или методы массива map / forEach.

Строка в вашем примере

array["3"] = "this should not be the first element";

очень отличается, однако, из-за того, что Javascript играет быстро и свободно с преобразованиями типов, это фактически устанавливает строку в 4-й слот в массиве:

const bar = [];
bar["3"] = "oops!"; // equivalent to bar[3] = "oops!"
console.log(bar); // [empty x 3, "oops!"]

Эта часть на самом деле Хорошая вещь (кроме части неявного преобразования), а не проблема: иногда вам нужен разреженный массив, и JS поддерживает их. Повторение его приведет к получению только одного элемента:

bar.forEach((item, index) => console.log(item, index)); // ["oops", 3]

Обратите внимание, что строка имеет правильный индекс 3, и к ней можно получить доступ таким образом, даже если перед ней ничего нет:

bar[3]; // "oops"

Итак, первые два назначения в вашем примере создают свойства объекта массива, а третье назначение - единственное, которое фактически добавляет элемент в массив по 4-му индексу (в первых 3 нет ничего) .

То, что вы, похоже, хотите, как предполагает Риз Кейси, является простым объектом:

const foo = {}; // curly
foo["some string"] = "whatever";

Однако теперь свойства в основном неупорядочены. Если вы хотите, чтобы они были в гарантированно заданном порядке c, вы do хотите получить массив, но все ваши индикаторы должны быть целыми числами и должны быть последовательными. Вы можете легко добиться этого, используя метод .push:

foo = [];
foo.push("something");
foo.push("something else");

Теперь foo будет иметь два элемента в правильном порядке и индексы 0 и 1 соответственно.

Обновление на основе прокомментируйте другой ответ:

Я хочу, чтобы некоторые данные были упорядочены, а остальные данные следовали

Это может быть достигнуто путем деструктуризации объекта:

const responseFromDB = {
  oneKeyICareAbout: 3,
  anotherKeyICareAbout: 2,
  foo: 6,
  bar: 7,
};

const {
  oneKeyICareAbout,
  anotherKeyICareAbout,
  *rest,
} = responseFromDB;

const stuffToDisplay = [
  oneKeyICareAbout,
  anotherKeyICareAbout,
  ...Object.values(rest),
]; // [3, 2, 6, 7]

И, по крайней мере, упорядоченный материал, который вы поместите в массив, будет упорядочен, потому что тем самым вы его заказали.

2 голосов
/ 29 февраля 2020

Javascript массивы не могут иметь строковые индексы. Это на самом деле работает некорректно, так как индекс добавляет свойство к объекту массива.

Изменение в объекте имеет больше смысла для этого.

РЕДАКТИРОВАТЬ: Хотя ниже упомянутого вы можете иметь строковые индексы вы на самом деле не используете массив, делая это. Ответ Джареда Смита дает гораздо более подробное объяснение, почему.

1 голос
/ 29 февраля 2020

Другие ответы объясняют, что происходит с вашей смесью массив-объект. Для наличия индексируемой вещи, которая может воспроизводить исходный порядок, вы можете использовать Map:

Объект Map содержит пары ключ-значение и запоминает исходную вставку порядок ключей.

array = new Map();
array.set("one","some data");
array.set("two","some more data");
array.set("3","this should not be the first element");

console.log("Test of get:",array.get("two"));
console.log("Test of order:");
for(let entry of array)
  console.log(entry);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...