Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
// A view of a Dictionary with its values mapped.
struct MapDictionary<Key: Hashable, BaseValue, Value>: Collection {
let _dict: [Key: BaseValue]
let _transform: (BaseValue) -> Value
init(_dict: [Key: BaseValue], transform: (BaseValue) -> Value) {
self._dict = _dict
self._transform = transform
}
// Collection
typealias Index = DictionaryIndex<Key, BaseValue>
var startIndex: Index { return _dict.startIndex }
var endIndex: Index { return _dict.endIndex }
var count: Int { return _dict.count }
func index(after i: Index) -> Index { return _dict.index(after: i) }
subscript(i: Index) -> (key: Key, value: Value) {
let pair = _dict[i]
return (pair.key, _transform(pair.value))
}
// Dictionary-ish
subscript(key: Key) -> Value? {
return _dict[key].flatMap(_transform)
}
var keys: AnyCollection<Key> {
return AnyCollection(self.lazy.map { $0.key })
}
var values: AnyCollection<Value> {
return AnyCollection(self.lazy.map { $0.value })
}
}
extension Dictionary {
func mappingValues<T>(transform: (Value) -> T) -> MapDictionary<Key, Value, T> {
return MapDictionary(_dict: self, transform: transform)
}
}
extension MapDictionary {
func mappingValues<T>(transform: (Value) -> T) -> MapDictionary<Key, BaseValue, T> {
return _dict.mappingValues { transform(self._transform($0)) }
}
}
// Usage
let words = [1: "one", 2: "two", 3: "three", 4: "four"]
let lengths = words.mappingValues { $0.characters.count }
let lengthWords = lengths.mappingValues { "\($0)" }
print(lengths[3])
// Optional(5)
for e in lengthWords.values {
print(e)
}
// 3
// 5
// 3
// 4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment