Last active
November 12, 2018 12:22
-
-
Save natecook1000/77ecc5a60b5b66901185d87c93e0664c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// A dictionary wrapper that uses a `CaseIterable` type as its key. | |
/// This differs from a dictionary in two ways: | |
/// | |
/// - Key-value pairs are accessed in a fixed order, which is the same | |
/// as the `Key`'s `allCases` property. | |
/// - Every possible key must have a value given, so using the key-based | |
/// subscript returns a non-optional value. | |
struct CaseMap<Key: CaseIterable & Hashable, Value> : Collection { | |
typealias Index = Key.AllCases.Index | |
var data: [Key: Value] | |
init(_ elements: [Key: Value]) { | |
assert(elements.count == Key.allCases.count) | |
for key in Key.allCases { | |
assert(elements.keys.contains(key)) | |
} | |
self.data = elements | |
} | |
var startIndex: Index { | |
return Key.allCases.startIndex | |
} | |
var endIndex: Index { | |
return Key.allCases.endIndex | |
} | |
func index(after i: Index) -> Index { | |
assert(i != endIndex) | |
return Key.allCases.index(after: i) | |
} | |
func mapValues<T>(_ transform: (Value) -> T) -> CaseMap<Key, T> { | |
return CaseMap<Key, T>(data.mapValues(transform)) | |
} | |
subscript(i: Index) -> (key: Key, value: Value) { | |
return (Key.allCases[i], data[Key.allCases[i]]!) | |
} | |
subscript(key: Key) -> Value { | |
get { return data[key]! } | |
set { data[key]! = newValue } | |
} | |
} | |
// Usage: | |
enum Suit: String, CaseIterable { | |
case spades | |
case hearts | |
case clubs | |
case diamonds | |
} | |
Suit.allCases | |
// [Suit.spades, Suit.hearts, Suit.clubs, Suit.diamonds] | |
Suit.allCases.map({ $0.rawValue }) | |
// ["spades", "hearts", "clubs", "diamonds"] | |
let m = CaseMap<Suit, String>([.spades: "S", .hearts: "H", .clubs: "C", .diamonds: "D"]) | |
// ... | |
for (suit, char) in m { | |
print("\(suit): \(char)") | |
} | |
// spades: S | |
// hearts: H | |
// clubs: C | |
// diamonds: D | |
m[.clubs] | |
// "C" (no optionals here!) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment