从KeyValuePairs初始化字典uniqueKeysWithValues :)

问题描述

struct Data {
    let storage: [String: Int]
    
    init(_ pairs: keyvaluePairs<String,Int>) {
        storage = Dictionary(uniqueKeysWithValues: pairs)
    }
}

编译错误

初始化器'init(uniqueKeysWithValues :)'需要类型 'keyvaluePairs .Element'(aka'(键:字符串,值:Int)') 和'(String,Int)'等价

有什么比用keyvaluePairs初始化Dictionary(uniqueKeysWithValues :)更自然的呢?不可能直接做只是荒谬的!
requires '(key: String,value: Int)' and '(String,Int)' be equivalent等同!

解决方法

这是因为KeyValuePairs.Element有标签。

type(of: (key: "",value: 0)) == type(of: ("",0)) // false

您需要另一个重载或仅就地移除标签。

public extension Dictionary {
  /// Creates a new dictionary from the key-value pairs in the given sequence.
  ///
  /// - Parameter keysAndValues: A sequence of key-value pairs to use for
  ///   the new dictionary. Every key in `keysAndValues` must be unique.
  /// - Returns: A new dictionary initialized with the elements of
  ///   `keysAndValues`.
  /// - Precondition: The sequence must not have duplicate keys.
  @inlinable init<Elements: Sequence>(uniqueKeysWithValues keysAndValues: Elements)
  where Elements.Element == Element {
    self.init(
      uniqueKeysWithValues: keysAndValues.map { ($0,$1) }
    )
  }
}
XCTAssertEqual(
  Dictionary(
    uniqueKeysWithValues: ["?": "?","?‍♀️": "?‍♂️"] as KeyValuePairs
  ),.init(
    uniqueKeysWithValues: [("?","?"),("?‍♀️","?‍♂️")]
  )
)
,

您也可以使用reduce

storage = pairs.reduce(into: [String: Int]()) { $0[$1.key] = $1.value }

即使您在pairs中有重复的键,这也将起作用(当前,它从重复项中取出最后一项:

let data = Data(["a": 1,"b": 2,"a": 3] as KeyValuePairs)
print(data.storage) 
// ["a": 3,"b": 2]

如果需要它来带走第一件物品,您可以这样做:

storage = pairs.reduce(into: [String: Int]()) { $0[$1.key] = $0[$1.key] ?? $1.value }

(或更短)

storage = pairs.reduce(into: [String: Int]()) { $0[$1.0] = $0[$1.0] ?? $1.1 }

此打印:

let data = Data(["a": 1,"a": 3] as KeyValuePairs)
print(data.storage) 
// ["a": 1,"b": 2]
,

由于Swift不支持 Splatting (尚未),因此您可以通过以下方式实现它:

struct Data {
    let storage: [String: Int]

    init(_ pairs: KeyValuePairs<String,Int>) {
        storage = Dictionary(uniqueKeysWithValues: pairs.reduce(into: [String: Int]()) { $0[$1.0] = $1.1 } .map { $0 })
    }
}

用法:

let data = Data(KeyValuePairs(dictionaryLiteral: ("a",1),("b",2)))
,

•修复:

storage = Dictionary(uniqueKeysWithValues: Array(pairs))

•原因:
您尝试使用的方法是:

public init<S>(uniqueKeysWithValues keysAndValues: S) where S : Sequence,S.Element == (Key,Value)

它缺少S.Element == (Key,Value)的合规性。

•再进一步一点:
请注意,如果您有重复的键,则会出现错误。您可以使用:

storage = Dictionary(Array(paris)) { _,new in
    return new //if you want to keep the last "key" value,or the reverse
}

•其他可能性:
convert [(key: String,value: String)] in [String:String]