首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否有一种声明式的方法将数组转换为字典?

是否有一种声明式的方法将数组转换为字典?
EN

Stack Overflow用户
提问于 2016-02-21 12:18:44
回答 7查看 18.2K关注 0票数 31

我想从这个字符串数组中得到

代码语言:javascript
复制
let entries = ["x=5", "y=7", "z=10"]

到这个

代码语言:javascript
复制
let keyValuePairs = ["x" : "5", "y" : "7", "z" : "10"]

我试着使用map,但问题似乎是字典中的键值对不是一个独特的类型,它只是在我的脑海中,但不在字典类型中,所以我无法真正提供转换函数,因为没有什么可转换的。加上map返回一个数组,所以这是一个“否”。

有什么想法吗?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2016-02-22 05:42:45

Swift 4

正如fl034所暗示的,这可以通过Swift 4简化一些,其中错误检查版本看起来如下:

代码语言:javascript
复制
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:

代码语言:javascript
复制
let foo = entries
    .map { $0.components(separatedBy: "=") }
    .reduce(into: [String:String]()) { dict, pair in
        if pair.count == 2 {
            dict[pair[0]] = pair[1]
        }
    }

老年TL;博士

减去错误检查,它看起来很像:

代码语言:javascript
复制
let foo = entries.map({ $0.componentsSeparatedByString("=") })
    .reduce([String:Int]()) { acc, comps in
        var ret = acc
        ret[comps[0]] = Int(comps[1])
        return ret
    }

使用map将[String]转换为一个拆分的[[String]],然后使用reduce构建[String:Int]字典。

或者,通过向Dictionary添加一个扩展

代码语言:javascript
复制
extension Dictionary {
    init(elements:[(Key, Value)]) {
        self.init()
        for (key, value) in elements {
            updateValue(value, forKey: key)
        }
    }
}

(顺便说一句,这是一个非常有用的扩展,您可以在字典上使用它来执行很多地图/筛选操作,这实际上是一种遗憾,它在默认情况下并不存在)

它变得更加简单:

代码语言:javascript
复制
let dict = Dictionary(elements: entries
    .map({ $0.componentsSeparatedByString("=") })
    .map({ ($0[0], Int($0[1])!)})
)

当然,您也可以组合两个映射调用,但我更喜欢分解单个转换。

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

代码语言:javascript
复制
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合并到flatMap中,或者为了简单起见将它们分开。

代码语言:javascript
复制
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
    }}
)
票数 53
EN

Stack Overflow用户

发布于 2016-02-21 13:39:12

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

代码语言:javascript
复制
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]).")
}

产出:

代码语言:javascript
复制
Value for key 'y' is Optional("7").
Value for key 'x' is Optional("5").
Value for key 'z' is Optional("10").

或者使用具有相同输出的单个reduce

代码语言:javascript
复制
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]).")
}
票数 9
EN

Stack Overflow用户

发布于 2017-11-29 11:14:24

使用Swift 4的新reduce(into: Result)方法:

代码语言:javascript
复制
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!
}

当然,您的字符串的拆分可以改进。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35536011

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档