【问题标题】:Reduce `[URLQueryItem]` into `[String: Any]`将 `[URLQueryItem]` 缩减为 `[String: Any]`
【发布时间】:2019-07-21 12:25:21
【问题描述】:

目前我有这个粗壮的reduce 函数...

blah: [String: Any] = queryItems.reduce([String: Any]()) {
    (params: [String: Any], queryItem: URLQueryItem) in

    var output = params

    output[queryItem.name] = queryItem.value

    return output
}

我确信有一种更简单的方法可以做到这一点,但我无法理解它是如何工作的。

有没有“更好”的方法来做到这一点?

“更好”是指更简洁、更短、更优雅等...

【问题讨论】:

  • 小警告:可以有多个具有相同键的参数,并且参数的顺序对于某些 API 很重要。将查询参数表示为字典时请注意这一点。
  • @Sulthan 感谢您的警告。对于我们的特定用例,这不是问题,但我会留意未来。另外......我将很快更新我的代码,所以最终可能不需要这个。 ??????

标签: swift reduce


【解决方案1】:

您可以使用每个查询项的名称和值创建字典

let items = urlComponents.queryItems ?? []
let dict = Dictionary(items.lazy.map { ($0.name, $0.value as Any) },
                      uniquingKeysWith: { $1 })

在重名的情况下,后面的值获胜(这可以通过uniquingKeysWith:参数控制)。

或者删除as Any 演员以获得[String: String?] 类型的字典:

let items = urlComponents.queryItems ?? []
let dict = Dictionary(items.lazy.map { ($0.name, $0.value ) },
                      uniquingKeysWith: { $1 })

或者

let items = urlComponents.queryItems ?? []
let dict = Dictionary(items.lazy.map { ($0.name, [$0.value] ) },
                      uniquingKeysWith: +)

构建[String : [String?]] 类型的字典,为每个名称保存所有值。

【讨论】:

    【解决方案2】:

    可以使用reduce(into:_:) 代替reduce(_:_)。这既可以为您节省行数,也可以为每次迭代节省复制 params 的开销:

    let blah: [String: Any] = (urlComponents.queryItems ?? []).reduce(into: [:]) {
        params, queryItem in 
        params[queryItem.name] = queryItem.value
    }
    

    当结果是写时复制类型(例如数组或字典)时,此方法优于 reduce(_:_:) 以提高效率。

    【讨论】:

    • reduce(into:) 是最近 Swift 中那些伟大的未知宝石之一。最后使非标量reduce 可用。
    • 而 Swift 是一种类型推断语言。顺便说一句,您可以在这里简单地使用可选链接let blah = urlComponents.queryItems?.reduce(into: [:]) { $0[$1.name] = $1.value } ?? [:] 如果值始终是字符串,则无需使用 Any 作为值类型
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    相关资源
    最近更新 更多