Есть ли индексированная коллекция значений в JavaScript? - PullRequest
0 голосов
/ 01 марта 2019

У меня простой вопрос: существует ли в JavaScript коллекция, которая может индексировать значение объекта, позволяет извлекать по значению объекта и может предоставлять ключи как объект по запросу?

Мой вариант использованияхочет контейнер, который может индексировать по координатам, например, x, y, z.(да, я знаю, что мог бы создать трехмерный массив).

Я более чем осведомлен о том, что стандартный объект индексирует и получает по строке, установка функции toString() для объекта позволит вам устанавливать и извлекать (в некоторой степени) прозрачно.

Мне также известно о Map<key, value>, который использует произвольный тип в качестве ключа, но затем использует стандартный === для сравнения ключей, что означает, что два объекта, равные по значению, не отображаются на один и тот жеvalue.

По сути, мне нужна карта, которая на самом деле использует значение ключа, а не идентификатор объекта для извлечения и предоставления значений.Мне кажется, что это будет очень распространенный вариант использования, но я не могу найти ни одной библиотеки npm, которая бы его удовлетворяла.Я на самом деле не хочу кататься самостоятельно, так есть ли библиотека или что-то, что я могу использовать для достижения своей цели?Я предполагаю, что мои поисковые термины просто сильно перегружены.

Простой код для демонстрации:

class Coord {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    toString() { return `${this.x}, ${this.y}`; }
}

let valueMap = new Map();
valueMap.set(new Coord(1, 1), `A set value`);
console.log(valueMap.get(new Coord(1, 1))); // prints 'undefined', 
                                            // want to get: 'A set value'

Ответы [ 2 ]

0 голосов
/ 03 марта 2019

Immutable.js обеспечивает это, но требует, чтобы вы использовали только типы и примитивы immutable.Это будет означать использование типов Record Immutable вместо классов *.Ваш пример в этом случае будет выглядеть так:

const { Record, Map } = require('immutable');
const Coord = Record({ a: 0, b: 0 }); // Record fields have default values

const valueMap = new Map().set(Coord(1, 1), `A set value`);
console.log(valueMap.get(Coord(1, 1))); // Logs "A set value"

Immutable.js может быть не совсем тем, что вы хотите, потому что все его коллекции, ну, в общем, неизменяемы.Каждая операция возвращает новую коллекцию, а не изменяет оригинал.К счастью, благодаря магии структурного разделения, это намного быстрее, чем можно было ожидать.

Я видел несколько альтернатив, но все они были реализованы неправильно (например, предполагая уникальность хэшей,строки вашего toString примера) или имели серьезные сложности или проблемы с производительностью при составлении карт.Например, Immutable.js позволяет использовать карту (или набор, или список, или карту наборов и т. Д.) В качестве ключа на другой карте.Несколько библиотек, которые я видел, которые правильно принимают хэш и функцию равенства в качестве аргументов для карты, либо пропускают эту сложность до конечного пользователя, либо имеют гораздо худшую производительность в этом случае.Наконец, библиотеки, которые зависят от значений хеш-функции, могут столкнуться с проблемами, если хранимый объект видоизменяется, поэтому использование библиотеки, обеспечивающей неизменность, может помочь избежать появления огнестрельного оружия.

Если Immutable.js вам не нравится,Есть несколько похожих библиотек. Mori был оригинальной библиотекой с неизменяемой структурой в JS и предоставляет несколько структур данных с семантикой значений (включая карты), но основан на Clojure и имеет очень неидиоматический интерфейс для JavaScript.В обеих этих библиотеках используются сопоставления массивов хеш-кодов для обеспечения эффективной реализации неизменяемых структур, и этот тип доступен в hamt.js .Тем не менее, Hamt очень прост и обеспечивает более сложный и менее сложный интерфейс, чем предыдущие два.


* Технически вы можете использовать свой собственный класс, реализуя Интерфейс Value Object и добавление методов equals и hashCode в ваши классы, но я считаю, что вы можете столкнуться с проблемами, если ваши объекты видоизменяются в то время как внутри коллекций Immutable.js, поэтому использование Records, вероятно, безопаснеев любом случае.

0 голосов
/ 01 марта 2019

Два объекта равны, если эти два объекта указывают на одну и ту же ссылку.Также нет смысла получать строковое значение из ссылки на объект.Вы можете установить эту строку в Object.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...