ã¢ãã¤ã«åºç¤ã°ã«ã¼ãã®ã´ã¡ã³ãµã³(@vincentisambart)ã§ãã
å æ¥ä»¥ä¸ã®ãã¤ã¼ããæè¦ãã¾ããã
Swift's stdlib moves to randomly seeded hashing: https://t.co/2T5oRYtD8B
— ericasadun (@ericasadun) 2018å¹´3æ10æ¥
ãã®å¤æ´ã¯Swift 4.1ã«ã¯ã¾ã å ¥ãã¾ãããã4.2ã5.0ã«å ¥ãã¯ãã§ããã³ã¼ãã¬ãã¥ã¼ã§ãã®å¤æ´ãåé¡ãèµ·ããããªã³ã¼ããææãããã¨ããã®ã§ãããã·ã¥å¤ã®ãããããããè¯ãã¿ã¤ãã³ã°ã§ã¯ãªãã§ããããã
Swiftã®ãã¨ãèãã¦æ¸ãã¦ãã¾ãããå¤ãã®ããã°ã©ãã³ã°è¨èªã«ãå½ã¦ã¯ã¾ãã¾ããããã·ã¥å¤ã¯Swiftã§ã¯hashValue
ã¨ããããããã£ãè¿ãã¾ãããå¤ãã®è¨èªã§ã¯åã«hash
ã¨ããã¡ã½ããã»é¢æ°ãè¿ãã¾ãã
ããã·ã¥ããã
ããã·ã¥å¤ã¯ããã·ã¥ããã(å¥åããã·ã¥ãã¼ãã«)ã«ä¸çªä½¿ãããã®ã§ã¯ãªãã§ãããããSwiftã§ã¯Dictionary
ãRubyã§ã¯Hash
ãC++ã§ã¯unordered_map
ãRustã§ã¯HashMap
ã¨å¼ã°ãããã®ã§ãã
ããã·ã¥ãããã¯ãããã®ä¸ç¨®ã§ãã£ã¦ããããã¨ããã®ã¯ãã¼ã«å¤ãçµã³ã¤ããããã®ãã®ã§ãã1ã¤ã®ãã¼ã«1ã¤ã®å¤ããçµã³ã¤ããªãå ´åãå¤ãã§ã(å¤ã¯é åã使ãã¾ãã)ãä¾ãã°æ¼«ç»ã®é£è¼éå§ã®å¹´ã®ããããä½ãã¨ä»¥ä¸ã®ããã«ãªãã¾ãã
ãã¼ | å¤ |
---|---|
ONE PIECE | 1997 |
DRAGON BALL | 1984 |
éã®ç¥é師 | 2009 |
Levius | 2012 |
å®å®å å¼ | 2007 |
ããã·ã¥ãããã¯åºæ¬çã«ãã¼ã«é ããªãå ´åãå¤ãã§ãããã¼ãæ¿å
¥ãããé ã§åæãããã¨ä¿è¨¼ããå®è£
(ä¾ãã°Rubyã®Hash
)ãããã¾ããã
ããã·ã¥ãããã®ãã¼ã«ä¸çªä½¿ãããã®ã¯æååã§ããã以ä¸ã®2ã¤ã®æ¡ä»¶ãæºããã°ä½ã§ã使ãã¾ãã
- 2ã¤ã®ãã¼ãçãããã©ããæ¯è¼ã§ãã(Swiftã§ã¯
Equatable
ã¨ãããããã³ã«ã«æºæ ãããã¨) - ãã¼ããããã·ã¥å¤ãè¨ç®ã§ãã(Swiftã§ã¯
Hashable
ã¨ãããããã³ã«ã«æºæ ãããã¨ãæ¯è¼ã§ããªãã¨ããã·ã¥å¤ã使ãç©ã«ãªããªãã®ã§Hashable
ã¯Equatable
ã«æºæ ãã¦ãã)
ããã·ã¥ãããã¯å¥ã®ãããã®ç¨®é¡ã«æ¯ã¹ã¦ã©ãããã¡ãªãããããã¨è¨ãã¾ãã¨ãããã·ã¥é¢æ°(ããã·ã¥å¤ãè¨ç®ããé¢æ°)ãè¯ããã°ããã¼ãå¤ãã¦ãå¤ãæ©ãåå¾ã§ããã¨ããã§ãã
ããã·ã¥å¤ã¨ãããçæããããã·ã¥é¢æ°
ããã·ã¥ãããã«ä½¿ãããããã·ã¥å¤ã¯åºæ¬çã«32-bitã64-bitã®æ´æ°ã§ããããã·ã¥å¤ãå ã«ãã¼ã¨å¤ãã¡ã¢ãªä¸ã©ãã«ç½®ãããã®ã決ã¾ãã¾ãã
ããã·ã¥ãããã§ä½¿ãã«ã¯ãããã·ã¥å¤ã以ä¸ã®æ¡ä»¶ãæºããå¿ è¦ãããã¾ãã
- ããã°ã©ã ãçµäºããã¾ã§ãããã·ã¥é¢æ°(ããã·ã¥å¤ãè¨ç®ããé¢æ°)ã«åããã¼ã渡ãã¨å¿ ãåãããã·ã¥å¤ãè¿ãã¹ã
- ããã·ã¥å¤ãéã£ã¦ããã°ãããã·ã¥é¢æ°ã«æ¸¡ããããã¼ãç°ãªãã¹ã
- éã2ã¤ã®ãã¼ãåãããã·ã¥å¤ãæã£ã¦ãè¯ããå¯å¤é·ã®æååããè¨ç®ãããããã·ã¥å¤ãåºå®é·æ°ãã¤ãã ãã«åã¾ãã®ã§ããã¹ã¦ã®ãã¼ãéãããã·ã¥å¤ãæã¤ã¯ããããã¾ããã
ä¸è¨ã®æ¡ä»¶ãæºããä¸çªã·ã³ãã«ãªããã·ã¥é¢æ°ãåºå®å¤ãè¿ãã ãã§ããããã ã¨ããã·ã¥ãããã¯ä¸å¿åãã¾ãããæ§è½ããããè½ã¡ã¦ãããã·ã¥ãããã使ãã¡ãªããããªããªãã¾ãã
ããã·ã¥å¤ãè¨ç®ããããã·ã¥é¢æ°ãªãã§ãããè¯ãããã·ã¥é¢æ°ã¯ããã·ã¥å¤ã®è¨ç®ãéãã¦ãè²ããªãã¼ã渡ãã¨ã§ããã ãéãããã·ã¥å¤ãè¿ãã¦ãããæ¹ãããã·ã¥ãããã®æ§è½ãåºã¾ããè¯ãããã·ã¥é¢æ°ãä½ãã®ã¯ããã大å¤ãªã®ã§ãæ¢åã®ç 究ããããã®ã使ãããå ´åãå¤ãã§ãã
æ°ãä»ããã¹ãã¨ãã
ããã·ã¥å¤ãæºããã¹ãæ¡ä»¶ã«ãããã°ã©ã ãçµäºããã¾ã§ãããã·ã¥é¢æ°ã«åããã¼ã渡ãã¨å¿ ãåãå¤ãè¿ããã¨æ¸ãã¾ãããããããã°ã©ã ãçµäºããã¾ã§ããéè¦ã§ããããã°ã©ã ãã¾ãå®è¡ããã¨å¤ããå¯è½æ§ãããã¾ããRubyã§è©¦ãã¦ã¿ãã¨åãããããã¨æãã¾ãã
$ ruby -e 'p "abcd".hash' -2478909447338366169 $ ruby -e 'p "abcd".hash' 3988221876519392566 $ ruby -e 'p "abcd".hash' -771890369285024305
ä»ã¾ã§Swiftã§ã¯ããã°ã©ã ãä½åå®è¡ãã¦ãæ¨æºã®hashValue
ãæ¯ååãããã·ã¥å¤ãè¿ãã¦ãã¾ãããããã®è¨äºã®é ã«ãªã³ã¯ããã¦ããå¤æ´ã§ããã°ã©ã ãå®è¡ããã度ã«ããã·ã¥å¤ãå¤ããããã«ãªãã¾ãã
ã©ããã¦å¤ããããã«ãªã£ãã®ãã¨è¨ãã¾ãã¨ãDoSæ»æã®ãªã¹ã¯ãä¸ããããã§ããDoSæ»æã¨ããã®ã¯ç°¡åã«ããã¨ãã·ã³ãããã¹ãå¦çã«è¿½ãã¤ããªããªããã¨ã§ãã
ããã·ã¥ãããã«åãããã·ã¥å¤ãæã¤ãã¼ãããããå ¥ããã¨ãæ§è½ãã©ãã©ãã¨è½ã¡ã¦ããã¾ããããã·ã¥å¤ãäºåã«äºæ¸¬ã§ããã¨åãããã·ã¥å¤ãæã¤ãã¼ã大éç¨æã§ãã¾ãããµã¼ãã¼ãããã·ã¥ãããã®ãã¼ã«ããããªãã®(ä¾ãã°ãªã¯ã¨ã¹ãã®å¼æ°å)ã«ç¨æããã大éã®ãã¼ã使ããã¦ãµã¼ãã¼ãããã¹ãå¦çã«è¿½ãã¤ããªããªãã¾ãã
ããã·ã¥å¤ãããã°ã©ã ã®å®è¡ãã¨ã«å¤ããã¨ãããã·ã¥å¤ã®äºæ¸¬ãããªãå°é£ã«ãªãã®ã§ãªã¹ã¯ãæ¸ããã¾ãã
ããã·ã¥ããã
ã§ãã©ããã¦åãããã·ã¥å¤ãå¤ãã¨ããã·ã¥ãããã®æ§è½ãè½ã¡ã¦ããã®ã§ãããããç解ããã«ã¯ããã·ã¥ãããã®ä»çµã¿ããã£ã¨ç´°ããè¦ãå¿ è¦ãããã¾ãã
ããã·ã¥ãããã®ã³ã¢ãªé¨åãåãªãé åã§ããé åã®é ç®ããã±ãã(bucket)ã¨å¼ã°ãã¦ãã¾ãã
é åã®ãµã¤ãº(ãã±ããæ°)ã«æºããã¹ãæ¡ä»¶ãç¹ã«ããã¾ããããåºæ¬çã«é ç®ãå¢ããã¨ãã£ã¨å¤§ããé åãç¨æããã¦ã以åã®é ç®ãæ°ããé åã«ç§»ãæ¿ãã¾ã(æ°ããé åã§ãã±ãããå¤ããå¯è½æ§ããã®ã§è¦æ³¨æ)ã
æ¿å ¥ããããã¼ã¨å¤ãã©ãã«å ¥ãã®ãã¯ããã·ã¥å¤ã§æ±ºã¾ãã¾ãããã±ããæ°ãããã·ã¥å¤ã®æ°ã»ã©å¤ãããã§ã¯ãªãã®ã§ãã¢ã¸ã¥ã(å°ä½æ¼ç®)ã使ã£ã¦ãã±ããæ°ä»¥ä¸ã«ãã¾ãã
let hashValue = key.hashValue // è² ã®ã¤ã³ããã¯ã¹ã ã¨å°ãã®ã§çµ¶å¯¾å¤ãåã let bucketIndex = abs(hashValue) % buckets.count // ããã·ã¥å¤ã¯å¾ã§ã¾ãè¨ç®ã§ãããã©ãåè¨ç®ãæ¸ããããã«å ¥ãã¦ãã buckets[bucketIndex] = Bucket(hashValue: hashValue, key: key, value: value)
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|
空 | 空 | 空 | 空 | 空 | 空 | 空 | 空 |
ããã·ã¥å¤ã-3272626601332557488
ã®ãã¼"ONE PIECE"
ãæ¿å
¥ããã¨ãabs(hashValue) % 8
ã0
ãªã®ã§ä»¥ä¸ã®ããã«ãªãã¾ãã
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|
"ONE PIECE" â 1997 |
空 | 空 | 空 | 空 | 空 | 空 | 空 |
ããã·ã¥å¤ã4799462990991072854
ã®ãã¼"éã®ç¥é師"
ãæ¿å
¥ããã¨ãabs(hashValue) % 8
ã6
ãªã®ã§ä»¥ä¸ã®ããã«ãªãã¾ãã
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|
"ONE PIECE" â 1997 |
空 | 空 | 空 | 空 | 空 | "éã®ç¥é師" â 2009 |
空 |
ãã ããããã ã¨åããã±ããã«å¥ã®ãã¼ãå ¥ã£ã¦ãããä»£å ¥ããã¨åã®ãã¼ããªããªãã¾ããåããã±ããã«è¤æ°ã®ãã¼ãå ¥ãã±ã¼ã¹ãè¡çª(collision)ã¨ããã¾ãã
è¡çªã®æ±ãã¯æ§ã ããã¾ããä¸çªã·ã³ãã«ãªã®ã¯é£çµãªã¹ããåçé åã§ãããä¾ãã°ãã¼ã次ã«ç©ºãã¦ãããã±ããã«å ¥ãããã¨ãããã¾ãã
ããã·ã¥å¤ã4799462990991072854
ã®ãã¼"å®å®å
å¼"
ãæ¿å
¥ããã¨ãabs(hashValue) % 8
ã6
ãªã®ã§ä»¥ä¸ã®ããã«ãªãã¾ãã
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|
"ONE PIECE" â 1997 |
空 | 空 | 空 | 空 | 空 | "éã®ç¥é師" â 2009 |
空 |
"å®å®å
å¼" â 2007 |
ã·ã³ãã«ãªããã·ã¥ããããå®è£ ãã¦ã¿ãã¨ä»¥ä¸ã®ããã«ãªãã¾ãã
import Foundation struct SimpleDictionary<Key: Hashable, Value> { typealias HashValue = Int struct BucketElement { var hashValue: HashValue // ãã¼ããè¨ç®ã§ãããã©æéæããã®ã§æ®ãã¦ãã var key: Key var value: Value } // é£çµãªã¹ãããã使ãããããå®è£ ããã£ã¨åãããããããããå¯å¤é·ã®é åã使ã typealias Bucket = [BucketElement] // å®è³ªé åã®é å var buckets: [Bucket] init() { // åãããããã®ãããã±ããæ°ãåºå®ã«ãã¦ããããæ®æ®µãã¼ãå¢ããã¨ãã¼ã¿ããã£ã¨å¤§ããé åã«ç§»ãæ¿ãã // 移ãæ¿ããæããã±ããæ°ãå¤ãã£ã¦ãã¼ã®ãã±ãããå¤ããå¯è½æ§ãããã®ã§ããã·ã¥å¤ãå ã«æ°ãããã±ãããå度è¨ç®ããå¿ è¦ããã let bucketCount = 8 buckets = Array<Bucket>(repeating: [], count: bucketCount) } subscript(key: Key) -> Value? { get { // ããã·ã¥å¤ã§ãã±ããã決ã¾ã let hashValue = key.hashValue let bucketIndex = abs(hashValue) % buckets.count for element in buckets[bucketIndex] { // ããã·ã¥å¤ã®æ¯è¼ãæ©ãã®ã§ã¾ãããã·ã¥å¤ãæ¯è¼ãã¦ãã if element.hashValue == hashValue && element.key == key { return element.value } } return nil } set(newValue) { let hashValue = key.hashValue let bucketIndex = abs(hashValue) % buckets.count // ãã¼ãæ¢ã«ä½¿ãã¦ããå ´åããã±ããå ã©ã®ã¤ã³ããã¯ã¹ã«å ¥ã£ã¦ããã®ã let indexInsideBucket = buckets[bucketIndex].index { element in element.hashValue == hashValue && element.key == key } if let nonNilNewValue = newValue { let newElement = BucketElement( hashValue: hashValue, key: key, value: nonNilNewValue ) if let nonNilIndexInsideBucket = indexInsideBucket { // ãã¼ãæ¢ã«å ¥ã£ã¦ããã®ã§ç½®ãæã buckets[bucketIndex][nonNilIndexInsideBucket] = newElement } else { // ãã¼ãã¾ã å ¥ã£ã¦ããªãã£ãã®ã§ãæ¿å ¥ buckets[bucketIndex].append(newElement) } } else { // newValueãnilãªã®ã§ãåé¤ if let nonNilIndexInsideBucket = indexInsideBucket { buckets[bucketIndex].remove(at: nonNilIndexInsideBucket) } } } } }
èå¿ãªã¨ããã¯è¡çªã®æ±ãã§ããåããã±ããã«ãã¼ãå¢ããã¨ããã±ããã«å ¥ã£ã¦ããé ç®ã®ãªã¹ããå°ããã¤ä¼¸ã³ã¾ããé ç®ãå¢ããã¨èªã¿è¾¼ã¿ãæ¸ãè¾¼ã¿ãæ¯è¼ãå¢ãã¦å¦çãéããªãã¾ãããã±ããã«é ç®ã1ã¤ãããªãã£ãå ´åãã¢ã¯ã»ã¹ããæã¯è¡ãããã®ã¯ããã·ã¥å¤ã®è¨ç®1åã¨ãããã·ã¥å¤ã®æ¯è¼1åã¨ããã¼èªä½ã®æ¯è¼1åã§ããåãããã·ã¥å¤ã®ãã¼ã100åå ¥ã£ã¦ããã¨ãå ¨é¨åããã±ããã«ãªãã®ã§ãã¢ã¯ã»ã¹ããã¨è¡ãããã®ã¯ããã·ã¥å¤ã®è¨ç®1åã¨ãããã·ã¥å¤ã®æ¯è¼100åã¨ããã¼èªä½ã®æ¯è¼100åã§ãã100åç®ãªã®ã§ãåã®99ååã®æ¿å ¥ããã¡ããããã¾ãã
éã«ãã¹ã¦ã®ãã¼ãå¥ã®ãã±ããã«å ¥ãã¨æ¿å ¥ãã度ã«æ¯è¼ã¯å1åã ãã§ããã§ãã®ã§ã§ããã ãå¤ãã®ãã±ããã使ãããæ¹ãæ§è½ãåºã¾ãã
ã³ã¼ãã¬ãã¥ã¼ã§æ°ã¥ããééã
ãã®è¨äºã®åé ã§ããã·ã¥å¤ã«é¢ããééããææããã¨è¨ãã¾ããããå ·ä½çã«ããã¨å¤§ããééãã以ä¸ã®2ã¤ã§ããã
==
ã®å®è£ ãhashValue
ãæ¯è¼ãã¦ããã ã
struct Foo: Hashable { static func == (lhs: Foo, rhs: Foo) -> Bool { return lhs.hashValue == rhs.hashValue } }
lhs
ã¨rhs
ãéã£ã¦ããããã·ã¥å¤ãåãã®å¯è½æ§ãããã¾ããããã·ã¥å¤ãéã£ã¦ãããlhs
ã¨rhs
ãå¿
ãéãã¾ããã©ã
hashValue
ãUserDefaults
ã«ä¿åããã¦ãã
UserDefaults.standard.integer(forKey: fooHashValueKey) (...) UserDefaults.standard.set(foo.hashValue, forKey: fooHashValueKey)
ããã°ã©ã ã®æ¬¡ã®å®è¡ã§ããã·ã¥å¤ãå¤ããå¯è½æ§ãããã¾ããå
ããHashable
ã®å
¬å¼ããã¥ã¡ã³ãã«ã¯æ確ã«æ¸ãã¦ããã¾ããã
Hash values are not guaranteed to be equal across different executions of your program. Do not save hash values to use in a future execution.
å®éåé ã§ãªã³ã¯ããå¤æ´ãSwiftã«å ¥ã£ãããããã°ã©ã ã®æ¬¡ã®å®è¡ã§ããã·ã¥å¤ãå¤ãã£ã¦ããªãå¯è½æ§ã極ãã¦ä½ãã§ãã
ã¾ã¨ã
ããã·ã¥å¤ãæ±ã£ã¦ããå ´åã以ä¸ã®é ç®ãè¦ãã¦ããã¾ãããã
- ããã·ã¥å¤ã¯ããã°ã©ã ã®å®è¡ãã¨ã«å¤ããå¯è½æ§ãããããã£ã¹ã¯ã«ä¿åãã¦ã¯ãããªã(å¥ã®å®è¡ã§ãåãçµæãè¿ãããã·ã¥é¢æ°ãæå³çã«ä½¿ããªãéã)
- 2ã¤ã®ãã¼ã®ããã·ã¥å¤ãéã£ããããã¼ãå¿ ãéã
- 2ã¤ã®ãã¼ã®ããã·ã¥å¤ã¯ãåãã ã¨ãã¦ãããã¼ãåãã ã¨éããªã