Почему бы не хэшировать свои объекты вручную и не использовать полученные строки в качестве ключей для обычного словаря JavaScript? В конце концов, вы в лучшем положении, чтобы знать, что делает ваши объекты уникальными. Это то, что я делаю.
Пример:
var key = function(obj){
// some unique object-dependent key
return obj.totallyUniqueEmployeeIdKey; // just an example
};
var dict = {};
dict[key(obj1)] = obj1;
dict[key(obj2)] = obj2;
Таким образом, вы можете контролировать индексирование, выполняемое JavaScript, без значительного увеличения объема памяти и обработки переполнения.
Конечно, если вы действительно хотите «решение промышленного уровня», вы можете создать класс, параметризованный функцией ключа и со всеми необходимыми API контейнера, но & hellip; мы используем JavaScript и пытаемся быть простыми и легкими, поэтому это функциональное решение является простым и быстрым.
Функция ключа может быть такой же простой, как выбор правильных атрибутов объекта, например, ключа или набора ключей, которые уже являются уникальными, комбинации клавиш, которые вместе уникальны, или такой сложной, как использование некоторых криптографические хэши, как в DojoX Encoding или DojoX UUID . Хотя последние решения могут создавать уникальные ключи, лично я стараюсь избегать их любой ценой, особенно если я знаю, что делает мои объекты уникальными.
Обновление в 2014 году: В 2008 году ответили, что это простое решение все еще требует дополнительных объяснений. Позвольте мне прояснить идею в форме вопросов и ответов.
Ваше решение не имеет реального хэша. Где это ???
JavaScript - это язык высокого уровня. Его основной примитив
( Объект * +1025 *)
включает в себя хэш-таблицу для сохранения свойств. Эта хеш-таблица обычно пишется
на языке низкого уровня для эффективности. Используя простой объект со строковыми ключами, мы используем эффективно реализованную хеш-таблицу без каких-либо усилий с нашей стороны.
Откуда вы знаете, что они используют хеш?
Существует три основных способа сохранить коллекцию объектов, адресуемых ключом:
- Unordered. В этом случае, чтобы получить объект по его ключу, мы должны пройти все ключи, останавливаясь, когда мы его находим. В среднем для сравнения потребуется n / 2.
- Заказанный.
- Пример # 1: отсортированный массив & mdash; выполняя бинарный поиск, мы найдем наш ключ после сравнения ~ log2 (n) в среднем. Намного лучше.
- Пример # 2: дерево. Опять это будет ~ log (n) попыток.
- Хеш-таблица. В среднем это требует постоянного времени. Сравните: O (n) против O (log n) против O (1). Boom.
Очевидно, что объекты JavaScript используют хеш-таблицы в той или иной форме для обработки общих случаев.
Действительно ли производители браузеров используют хеш-таблицы ???
Действительно.
Они обрабатывают столкновения?
Да. Смотри выше. Если вы обнаружили столкновение с неравными строками, не стесняйтесь сообщать об ошибке поставщику.
Так что вы думаете?
Если вы хотите хешировать объект, найдите, что делает его уникальным, и используйте его в качестве ключа. Не пытайтесь вычислять реальный хеш или эмулировать хеш-таблицы & mdash; он уже эффективно обрабатывается базовым объектом JavaScript.
Используйте этот ключ с JavaScript Object
, чтобы использовать встроенную хэш-таблицу, избегая возможных конфликтов со свойствами по умолчанию.
Примеры, с чего можно начать:
- Если ваши объекты содержат уникальное имя пользователя & mdash; используйте его как ключ.
- Если он содержит уникальный номер клиента & mdash; используйте это как ключ.
- Если он включает в себя уникальные номера, выданные правительством, такие как номер SSN или номер паспорта, и ваша система не допускает дублирование & mdash; используйте его как ключ.
- Если комбинация полей уникальна & mdash; используйте это как ключ.
- Штатная аббревиатура + номер водительского удостоверения - отличный ключ.
- Аббревиатура страны + номер паспорта тоже отличный ключ.
- Некоторые функции для полей или всего объекта могут возвращать уникальное значение & mdash; используйте его как ключ.
Я использовал ваше предложение и кэшировал все объекты, используя имя пользователя. Но какого-то мудрого парня зовут «toString», который является встроенным свойством! Что мне теперь делать?
Очевидно, что если даже отдаленно возможно, что полученный ключ будет состоять исключительно из латинских символов, вы должны что-то с этим сделать. Например, добавьте любые нелатинские символы Юникода, которые вам нравятся в начале или в конце, чтобы снять конфликт со свойствами по умолчанию: "#toString", "#MarySmith". Если используется составной ключ, разделите ключевые компоненты, используя некий латинский разделитель: «имя, город, штат».
В общем, это место, где мы должны проявлять креативность и выбирать самые простые ключи с заданными ограничениями (уникальность, потенциальные конфликты со свойствами по умолчанию).
Примечание: уникальные ключи не конфликтуют по определению, в то время как потенциальные конфликты хешей будут обрабатываться базовым Object
.
Почему вам не нравятся промышленные решения?
ИМХО, лучший код - это вовсе не код: он не содержит ошибок, не требует обслуживания, прост в понимании и выполняется мгновенно. Все «хеш-таблицы в JavaScript», которые я видел, были> 100 строками кода и включали несколько объектов. Сравните это с: dict[key] = value
.
Еще один момент: возможно ли даже превзойти производительность изначального объекта, написанного на низкоуровневом языке, с использованием JavaScript и тех же самых изначальных объектов для реализации того, что уже реализовано?
Я все еще хочу хешировать свои объекты без каких-либо ключей!
Нам повезло: ECMAScript 6 (выпуск запланирован на середину 2015 года, дайте или возьмите 1-2 года после этого, чтобы стать широко распространенным) определяет
карта и
набор .
Судя по определению, они могут использовать адрес объекта в качестве ключа, что позволяет мгновенно различать объекты без искусственных ключей. OTOH, два разных, но одинаковых объекта, будут отображаться как отдельные.
Сравнительная разбивка от MDN :
Объекты похожи на Карты в том, что оба позволяют вам устанавливать ключи к значениям,
получить эти значения, удалить ключи и определить, является ли что-то
хранится в ключе. Из-за этого (и потому что не было встроенного
альтернативы), Объекты исторически использовались как Карты; тем не мение,
Есть важные отличия, которые делают использование карты предпочтительным в
некоторые случаи:
- Ключами объекта являются строки и символы, в то время как они могут иметь любое значение для карты, включая функции, объекты и любые примитивы.
- Ключи в Map упорядочены, а ключи, добавленные к объекту, не упорядочены. Таким образом, при выполнении итерации объект Map возвращает ключи в порядке
вставки.
- Вы можете легко получить размер Карты с помощью свойства size, в то время как количество свойств в Объекте должно быть определено вручную.
- Карта является итеративной и, таким образом, может быть напрямую повторена, тогда как для итерации по объекту требуется получить его ключи некоторым способом
и перебирая их.
- Объект имеет прототип, поэтому на карте есть ключи по умолчанию, которые могут столкнуться с вашими ключами, если вы не будете осторожны. Начиная с ES5 это может
можно обойти с помощью map = Object.create (null), но это редко
сделано.
- Карта может работать лучше в сценариях, связанных с частым добавлением и удалением пар ключей.