I am making a structure that acts like a String
, except that it only deals with Unicode UTF-32 scalar values. Thus, it is an array of UInt32
. (See this question for more background.)
What I want to do
I want to be able to use my custom ScalarString
struct as a key in a dictionary. For example:
var suffixDictionary = [ScalarString: ScalarString]() // Unicode key, rendered glyph value
// populate dictionary
suffixDictionary[keyScalarString] = valueScalarString
// ...
// check if dictionary contains Unicode scalar string key
if let renderedSuffix = suffixDictionary[unicodeScalarString] {
// do something with value
}
Problem
In order to do that, ScalarString
needs to implement the Hashable Protocol. I thought I would be able to do something like this:
struct ScalarString: Hashable {
private var scalarArray: [UInt32] = []
var hashValue : Int {
get {
return self.scalarArray.hashValue // error
}
}
}
func ==(left: ScalarString, right: ScalarString) -> Bool {
return left.hashValue == right.hashValue
}
but then I discovered that Swift arrays don't have a hashValue
.
What I read
The article Strategies for Implementing the Hashable Protocol in Swift had a lot of great ideas, but I didn't see any that seemed like they would work well in this case. Specifically,
- Object property (array is does not have
hashValue
) - ID property (not sure how this could be implemented well)
- Formula (seems like any formula for a string of 32 bit integers would be processor heavy and have lots of integer overflow)
- ObjectIdentifier (I'm using a struct, not a class)
- Inheriting from NSObject (I'm using a struct, not a class)
Here are some other things I read:
- Implementing Swift's Hashable Protocol
- Swift Comparison Protocols
- Perfect hash function
- Membership of custom objects in Swift Arrays and Dictionaries
- How to implement Hashable for your custom class
- Writing a good Hashable implementation in Swift
Question
Swift Strings have a hashValue
property, so I know it is possible to do.
How would I create a hashValue
for my custom structure?
Updates
Update 1: I would like to do something that does not involve converting to String
and then using String
's hashValue
. My whole point for making my own structure was so that I could avoid doing lots of String
conversions. String
gets it's hashValue
from somewhere. It seems like I could get it using the same method.
Update 2: I've been looking into the implementation of string hash codes algorithms from other contexts. I'm having a little difficulty knowing which is best and expressing them in Swift, though.
- Java
hashCode
algorithm - C algorithms
- hash function for string (SO question and answers in C)
- Hashing tutorial (Virginia Tech Algorithm Visualization Research Group)
- General Purpose Hash Function Algorithms
Update 3
I would prefer not to import any external frameworks unless that is the recommended way to go for these things.
I submitted a possible solution using the DJB Hash Function.
UInt32
cannot handle SwiftCharacter
s (extended grapheme clusters), which can be composed of multiple Unicode scalar values. The reason I am making my ownScalarString
is to avoid some of the ambiguity ofCharacter
. – Calumet