是否有将Array转换为Dictionary的声明方法?

Ear*_*rey 31 declarative swift

我想从这个字符串数组中获取

let entries = ["x=5", "y=7", "z=10"]
Run Code Online (Sandbox Code Playgroud)

对此

let keyValuePairs = ["x" : "5", "y" : "7", "z" : "10"]
Run Code Online (Sandbox Code Playgroud)

我试图使用,map但问题似乎是字典中的键值对不是一个独特的类型,它只是在我的脑海中,但不是在字典类型,所以我无法真正提供转换函数,因为有什么都没有改变.再加上map一个阵列,所以不行.

有任何想法吗?

Dav*_*rry 52

斯威夫特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
        }
    }
Run Code Online (Sandbox Code Playgroud)

如果您不希望值为Ints,则更简单:

let foo = entries
    .map { $0.components(separatedBy: "=") }
    .reduce(into: [String:String]()) { dict, pair in
        if pair.count == 2 {
            dict[pair[0]] = pair[1]
        }
    }
Run Code Online (Sandbox Code Playgroud)

较旧的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
    }
Run Code Online (Sandbox Code Playgroud)

使用map将其[String]转换为拆分[[String]],然后[String:Int]使用reduce 构建字典.

或者,通过添加扩展名Dictionary:

extension Dictionary {
    init(elements:[(Key, Value)]) {
        self.init()
        for (key, value) in elements {
            updateValue(value, forKey: key)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

(相当有用的扩展顺便说一下,你可以用它来进行字典上的很多map/filter操作,真的很遗憾它默认不存在)

它变得更简单:

let dict = Dictionary(elements: entries
    .map({ $0.componentsSeparatedByString("=") })
    .map({ ($0[0], Int($0[1])!)})
)
Run Code Online (Sandbox Code Playgroud)

当然,您也可以组合两个地图调用,但我更喜欢拆分各个变换.

如果要添加一些错误检查,flatMap可以使用而不是map:

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
        }})
)
Run Code Online (Sandbox Code Playgroud)

同样,如果你愿意,你可以明显地合并mapflatMap或将它们分割为简单起见.

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
    }}
)
Run Code Online (Sandbox Code Playgroud)

  • 累积,组件和返回 (2认同)

Cro*_*man 9

一种方法是使用mapreduce以元组作为中间值的两个阶段,例如:

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]).")
}
Run Code Online (Sandbox Code Playgroud)

输出:

Value for key 'y' is Optional("7").
Value for key 'x' is Optional("5").
Value for key 'z' is Optional("10").
Run Code Online (Sandbox Code Playgroud)

或者使用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]).")
}
Run Code Online (Sandbox Code Playgroud)


fl0*_*034 8

使用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!
}
Run Code Online (Sandbox Code Playgroud)

当然,可以改进String的拆分.