У меня недавно была ошибка в моем коде, которая была связана с тем, что я пропустил текст «в порядке размещения» при просмотре деталей объекта карты в MDN. Короче говоря, у меня есть объект карты, скажем так
let myMap = new Map;
а затем, после заполнения, я перебираю его содержимое с помощью простого оператора для .. из. Как это
for (let [key, val] of myMap) {
...
}
Код в цикле для зависит от пары (ключ, значение), которая будет отсортирована по ключ. Однако алгоритм, заполняющий карту, делает это в случайном порядке (и я не могу это изменить). Чтобы обойти эту проблему, я сначала добавляю все возможные ключи к объекту карты, примерно так:
let myMap = new Map;
for (let i=0; i<maxkey; ++i) myMap.set(key(i), undefined);
// And in the for loop
for (let [key, val] of myMap) {
if (typeof val === "undefined") continue;
//...
}
К счастью, их не так много (поэтому снижение производительности незначительно), и это работает. Тем не менее, мне это решение кажется немного неудобным.
Есть что-нибудь получше?
массив типа [{ключ: T, значение: V}], затем arr.sort ((a, b) => compare (a.key, b.key))?
я думаю да, это вариант
The code in for loop depends on (key, value) pair to be sorted by key.
Тогда Map
- неправильная структура данных для вас. Его цель - быстрый поиск, а не поддержание порядка. Если вам нужна упорядоченная (сортируемая) последовательность, используйте массив. Или, если вам нужен как поиск, так и индивидуальный порядок, используйте их в комбинации. Для вашего конкретного случая с небольшим количеством известных ключей предварительное заполнение карты в порядке, в качестве альтернативы используйте их только для итерации
for (let key=0; key < maxkey; key++) {
if (myMap.has(key)) {
const val = myMap.get(key);
… // use key and value
}
}
Или, если ключей намного больше, чем хранится на карте, вы также можете сделать
for (const key of Array.from(myMap.keys()).sort((a, b) => a-b)) {
const val = myMap.get(key);
… // use key and value
}
Если вам нужно сделать это более одного раза, вы также можете реализовать свой собственный итератор.
Карты делать поддерживают порядок, порядок вставки. Вы хотите сказать, что карты не остаются отсортированный. Порядок массива такой же, как у карты, если вы явно не используете метод sort
.
@DavidCallanan Да, это то, что я хотел сказать - карты не могут быть переупорядочены. И даже если они используют фиксированный порядок для единообразия, заказ не является их основной целью.
Порядок ключей в карте зависит от реализации карты. Карта с естественно упорядоченными ключами часто называется древовидная карта, потому что ключи хранятся в дерево. Я не использовал древовидную карту в JS, поэтому не могу рекомендовать конкретную реализацию.
Преобразуйте его в массив и отсортируйте.
[...map].sort(([k1], [k2]) => k1.localeCompare(k2))