В Python> = 3.6 новая f-строка является эффективным способом конкатенации строки.
>>> name = 'some_name'
>>> number = 123
>>>
>>> f'Name is {name} and the number is {number}.'
'Name is some_name and the number is 123.'
Запустите с
NSUInteger prime = 31;
NSUInteger result = 1;
Тогда для каждого примитива, который Вы делаете
result = prime * result + var
Для 64 битов, которые Вы могли бы также хотеть сместить и xor.
result = prime * result + (int) (var ^ (var >>> 32));
Для объектов Вы используете 0 для ноля и иначе их хэш-кода.
result = prime * result + [var hash];
Для булевских переменных Вы используете два различных значения
result = prime * result + (var)?1231:1237;
<час> , Это не работа tcurdt, и комментарии просили больше объяснения, таким образом, я полагаю, что редактирование для атрибуции справедливо.
Этот алгоритм был популяризирован в книге "Эффективный Java", и , соответствующая глава может в настоящее время находиться онлайн здесь . Та книга популяризировала алгоритм, который является теперь значением по умолчанию во многих JAVA-приложениях (включая Eclipse). Это произошло, однако, от еще более старой реализации, которая по-разному приписывается Dan Bernstein или Chris Torek. Тот более старый алгоритм, первоначально пущенный в ход вокруг в Usenet и определенной атрибуции, является трудным. Например, существуют [приблизительно 116] интересный комментарий в этом коде Apache (ищите их имена), это ссылается на первоисточник.
Нижняя строка, это - очень старый, простой алгоритм хеширования. Это не является самым производительным, и это, как даже доказывают, математически не "хороший" алгоритм. Но это просто, и много людей использовало его в течение долгого времени с хорошими результатами, таким образом, это имеет большую историческую поддержку.
Обратите внимание, что при создании объекта, который может быть видоизменен после создания, значение хэш-функции должно не изменяться , если объект вставляется в набор. В сущности это означает, что значение хэш-функции должно быть зафиксировано от точки начального создания объекта. См. документация Apple относительно протокола NSObject - метод хеша для получения дополнительной информации:
, Если изменяемый объект добавляется к набору, который использует значения хэш-функции для определения object’s положения в наборе, значение, возвращенное методом хеша объекта, не должно изменяться, в то время как объект находится в наборе. Поэтому или метод хеша не должен полагаться ни на одну object’s информацию о внутреннем состоянии, или необходимо удостовериться, что object’s информация о внутреннем состоянии не изменяется, в то время как объект находится в наборе. Таким образом, например, изменяемый словарь может быть помещен в хэш-таблицу, но Вы не должны изменять его, в то время как это там. (Обратите внимание, что может быть трудно знать, является ли данный объект в наборе.)
Это походит на полный whackery мне, так как он потенциально эффективно представляет намного менее эффективные поиски хеша, но я предполагаю, что лучше допустить ошибку на стороне осторожности и следовать за тем, что говорит документация.
Я - новичок Objective C также, но я нашел превосходную статью об идентификационных данных по сравнению с равенством в Objective C здесь . От моего чтения похоже, что Вы могли бы быть в состоянии просто сохранить хеш-функцию по умолчанию (который должен обеспечить уникальные идентификационные данные), и реализуйте isEqual метод так, чтобы это сравнило значения данных.
Я нашел , эта страница , чтобы быть полезным руководством в переопределении равняется - и методы типа хеша. Это включает достойный алгоритм для вычисления хэш-кодов. Страница приспособлена к Java, но довольно легко адаптировать его к Objective-C/Cocoa.
Это непосредственно не отвечает на Ваш вопрос (вообще), но я использовал MurmurHash прежде для генерации хешей: Предположение murmurhash
я должен объяснить почему: murmurhash чертовски быстр...
Легкий, но неэффективный путь состоит в том, чтобы возвратить тот же -hash
значение для каждого экземпляра. Иначе, да, необходимо реализовать хеш, базирующийся только на объектах, которые влияют на равенство. Это хитро при использовании слабых сравнений в -isEqual:
(например, нечувствительные к регистру сравнения строк). Для ints можно обычно использовать сам интервал, если you’ll соответствовать NSNumbers.
Don’t используют | =, тем не менее, это будет насыщать. Используйте ^ = вместо этого.
Случайный забавный факт: [[NSNumber numberWithInt:0] isEqual:[NSNumber numberWithBool:NO]]
, но [[NSNumber numberWithInt:0] hash] != [[NSNumber numberWithBool:NO] hash]
. (rdar://4538282, откройтесь с 05 мая 2006)
Я просто беру Objective C сам, таким образом, я не могу говорить за тот язык а именно, но на других языках я использую, если два экземпляра "Равны", они должны возвратить тот же хеш - иначе Вы собираетесь иметь все виды проблем при попытке использовать их в качестве ключей в хеш-таблице (или любые наборы типа словаря).
, С другой стороны, если 2 экземпляра не равны, они могут или не могут иметь того же хеша - лучше, если они не делают. Вот в чем разница между O (1) поиск на хэш-таблице и O (N) поиск - если все Ваши хеши сталкиваются, можно найти, что поиск таблицы не лучше, чем поиск списка.
С точки зрения лучших практик Ваш хеш должен возвратить случайное распределение значений для его входа. Это означает, что, например, если у Вас есть двойное, но большинство Ваших значений имеет тенденцию кластеризироваться между 0 и 100, необходимо удостовериться, что хеши, возвращенные теми значениями, равномерно распределяются через весь диапазон возможных значений хэш-функции. Это значительно улучшит Вашу производительность.
существует много алгоритмов хеширования там, включая несколько перечисленные здесь. Я стараюсь не создавать новые хеш-алгоритмы, поскольку это может иметь большие последствия производительности, таким образом с помощью существующих методов хеша и делая поразрядную какую-то комбинацию, как Вы делаете в своем примере, хороший способ избежать его.
Куинн ошибается, что ссылка на хэш ропота здесь бесполезен. Куинн прав в том, что вы хотите понять теорию хеширования. Ропот превращает эту теорию в реализацию. Стоит изучить, как применить эту реализацию к этому конкретному приложению.
Некоторые из ключевых моментов здесь:
Пример функции из tcurdt предполагает, что '31' - хороший множитель, потому что он простое число. Нужно показать, что простота - необходимое и достаточное условие. На самом деле 31 (и 7), вероятно, не очень хорошие простые числа, потому что 31 == -1% 32. Нечетный умножитель с примерно половиной установленных бит и половиной битов свободными, вероятно, будет лучше. (Этим свойством обладает константа умножения хэша murmur.)
Этот тип хеш-функции, вероятно, был бы сильнее, если бы после умножения значение результата было скорректировано с помощью сдвига и xor. Умножение имеет тенденцию давать результаты большого количества битовых взаимодействий на верхнем конце регистра и низкие результаты взаимодействия на нижнем конце регистра. Сдвиг и xor увеличивают взаимодействие на нижнем конце регистра.
Установка начального результата на значение, при котором примерно половина битов равна нулю, а примерно половина битов равна единице, также может быть полезной.
может быть полезно внимательно следить за порядком, в котором объединяются элементы. Вероятно, сначала следует обработать логические значения и другие элементы, значения которых не сильно распределены.
Может быть полезно добавить пару дополнительных этапов битового скремблирования в конце вычислений.
Является ли хэш шумоподавления действительно быстрым для этого приложения - вопрос открытый. Хэш шума предварительно смешивает биты каждого входного слова. Несколько входных слов могут обрабатываться параллельно, что помогает конвейерному процессору с несколькими задачами.
Простите, если я рискну показаться здесь полным болваном, но ... ... никто не удосужился упомянуть, что для следования `` лучшим практикам '' вам определенно не следует указывать метод равенства, который НЕ будет учитывать все данные, принадлежащие вашему целевому объекту, например, любые данные, агрегированные для вашего объекта, по сравнению с его партнером, следует учитывать при реализации equals. Если вы не хотите принимать во внимание, скажем, «возраст» при сравнении, тогда вам следует написать компаратор и использовать его для выполнения сравнений вместо isEqual:.
Если вы определяете isEqual: метод, который выполняет равенство произвольное сравнение, вы подвергаетесь риску злоупотребления этим методом другим разработчиком или даже вами, если вы забыли «поворот» в своей интерпретации равенства.
Таким образом, хотя это отличный вопрос о хешировании, вы не должны Обычно нет необходимости переопределять метод хеширования, вместо этого вам, вероятно, следует определить специальный компаратор.