extension CollectionType {
func map2Dict<K, V>(@noescape map: ((Self.Generator.Element) -> (K, V)?)) -> [K: V] {
var d = [K: V]()
for e in self {
if let kV = map(e) {
d[kV.0] = kV.1
}
}
return d
}
func map2Array<T>(@noescape map: ((Self.Generator.Element) -> (T)?)) -> [T] {
var a = [T]()
for e in self {
if let o = map(e) {
a.append(o)
}
}
return a
}
func map2Set<T>(@noescape map: ((Self.Generator.Element) -> (T)?)) -> Set<T> {
return Set(map2Array(map))
}
}
这是示例用法 .
let entries = ["x=5", "y=7", "z=10"]
let dict:[String: String] = entries.map2Dict({
let components = $0.componentsSeparatedByString("=")
return (components.first!, components.last!)
})
print("dict \(dict)")
52
Swift 4
正如fl034所提到的,这可以通过Swift 4进行简化,其中错误检查版本如下所示:
let foo = entries
.map { $0.components(separatedBy: "=") }
.reduce(into: [String:Int64]()) { dict, pair in
if pair.count == 2, let value = Int64(pair[1]) {
dict[pair[0]] = value
}
}
如果您不希望值为Ints,则更简单:
let foo = entries
.map { $0.components(separatedBy: "=") }
.reduce(into: [String:String]()) { dict, pair in
if pair.count == 2 {
dict[pair[0]] = pair[1]
}
}
Older TL;DR
减去错误检查,它看起来非常像:
let foo = entries.map({ $0.componentsSeparatedByString("=") })
.reduce([String:Int]()) { acc, comps in
var ret = acc
ret[comps[0]] = Int(comps[1])
return ret
}
let dict2 = [String:Int](elements: entries
.map({ $0.componentsSeparatedByString("=") })
.flatMap({
if $0.count == 2, let value = Int($0[1]) {
return ($0[0], value)
} else {
return nil
}})
)
同样,如果你愿意,你可以显然将 map 合并到_178015中或者为了简单起见将它们分开 .
let dict2 = [String:Int](elements: entries.flatMap {
let parts = $0.componentsSeparatedByString("=")
if parts.count == 2, let value = Int(parts[1]) {
return (parts[0], value)
} else {
return nil
}}
)
extension Dictionary {
func withUpdate(key: Key, value: Value) -> Dictionary<Key, Value> {
var result = self
result[key] = value
return result
}
}
let entries = ["x=5", "y=7", "z=10"]
let keyValues = entries.flatMap { str -> (String, String)? in
let split = str.characters.split("=").map(String.init)
return split.count > 1 ? (split[0], split[1]) : nil
}
let keyValuePairs = keyValues.reduce([String: String]()) { $0.withUpdate($1.0, value: $1.1) }
0
一种方法是使用 map 和 reduce 两个阶段,以元组作为中间值,例如:
let entries = ["x=5", "y=7", "z=10"]
let dict = entries.map { (str) -> (String, String) in
let elements = str.characters.split("=").map(String.init)
return (elements[0], elements[1])
}.reduce([String:String]()) { (var dict, kvpair) in
dict[kvpair.0] = kvpair.1
return dict
}
for key in dict.keys {
print("Value for key '\(key)' is \(dict[key]).")
}
输出:
Value for key 'y' is Optional("7").
Value for key 'x' is Optional("5").
Value for key 'z' is Optional("10").
或者使用具有相同输出的单个 reduce :
let entries = ["x=5", "y=7", "z=10"]
let dict = entries.reduce([String:String]()) { (var dict, entry) in
let elements = entry.characters.split("=").map(String.init)
dict[elements[0]] = elements[1]
return dict
}
for key in dict.keys {
print("Value for key '\(key)' is \(dict[key]).")
}
0
使用 Swift 4 的新 reduce(into: Result) 方法:
let keyValuePairs = entries.reduce(into: [String:String]()) { (dict, entry) in
let key = String(entry.first!)
let value = String(entry.last!)
dict[entry.first!] = entry.last!
}
当然,可以改进String的拆分 .
0
对于喜欢超载和单线的其他人 .
public func +<K, V>(lhs: [K:V], rhs: [K:V]) -> [K:V] {
var lhs: [K:V] = lhs
for (key, value) in rhs {
lhs[key] = value
}
return lhs
}
let array = ["x=5", "y=7", "z=10"]
let dictionary = array.map({ $0.componentsSeparatedByString("=") }).reduce([:]) { $0 + [$1[0]: $1[1]] }
print(dictionary) // ["y": "7", "x": "5", "z": "10"]
8 回答
好的答案已经 . 以下是集合类型扩展的另一种方法 . 您可以将任何集合类型转换为字典,数组或集合 .
这是示例用法 .
Swift 4
正如fl034所提到的,这可以通过Swift 4进行简化,其中错误检查版本如下所示:
如果您不希望值为Ints,则更简单:
Older TL;DR
减去错误检查,它看起来非常像:
使用map将
[String]
转换为拆分[[String]]
,然后使用reduce构建[String:Int]
的字典 .或者,通过添加
Dictionary
的扩展名:(相当有用的扩展顺便说一句,你可以在字典上使用它进行很多map / filter操作,真的很遗憾它默认不存在)
它变得更简单:
当然,您也可以组合两个 Map 调用,但我更喜欢拆分各个变换 .
如果要添加一些错误检查,可以使用
flatMap
而不是map
:同样,如果你愿意,你可以显然将
map
合并到_178015中或者为了简单起见将它们分开 .我喜欢@paulgriffiths的答案,但是如果你对运行时错误有极大的厌恶,你可以更进一步,以确保初始数组中的每个字符串实际上都有两个必需的元素......
与其他代码相比,此代码的重要区别在于我检查以确保字符串中实际上存在"=",并且两侧都有元素 .
flatMap
有效地过滤掉任何失败的内容 .一种方法是使用
map
和reduce
两个阶段,以元组作为中间值,例如:输出:
或者使用具有相同输出的单个
reduce
:使用 Swift 4 的新
reduce(into: Result)
方法:当然,可以改进String的拆分 .
对于喜欢超载和单线的其他人 .
如果您有两个并行数组,则可以使用
zip()
,Array()
和David Berry's Dictionary extension:别忘了添加扩展名:
简单方法:
输出:
更复杂的方式:
输出: