Arrays Swift 3:数组到字典?

Arrays Swift 3:数组到字典?,arrays,dictionary,filter,swift3,Arrays,Dictionary,Filter,Swift3,我有一个大数组,需要通过键(查找)访问它,所以我需要创建字典。Swift 3.0中是否有内置函数来执行此操作,还是需要我自己编写 首先,我将需要一个键为“String”的类,然后,也许我将能够编写一个通用的模板版本(所有类型的数据和键) 2019年的附注。这是Swift 5、具有值的UniqueKeys和类似调用的内置功能。正如其他人所说,我们需要了解哪些是键 然而,我试图为我对你的问题的解释提供一个解决方案 struct User { let id: String let f

我有一个大数组,需要通过键(查找)访问它,所以我需要创建字典。Swift 3.0中是否有内置函数来执行此操作,还是需要我自己编写

首先,我将需要一个键为“String”的类,然后,也许我将能够编写一个通用的模板版本(所有类型的数据和键)



2019年的附注。这是Swift 5、具有值的UniqueKeys和类似调用的内置功能。

正如其他人所说,我们需要了解哪些是键

然而,我试图为我对你的问题的解释提供一个解决方案

struct User {
    let id: String
    let firstName: String
    let lastName: String
}
这里我假设两个具有相同
id
的用户不可能存在

现在,
dict
是一个字典,
用户id
用户值

要通过用户的
id
访问用户,现在只需编写

let user = dict["123"]
更新#1:一般方法 给定给定类型
元素
的数组,以及确定
元素
的闭包,以下通用函数将生成类型为
[键:元素]
字典

func createIndex<Key, Element>(elms:[Element], extractKey:(Element) -> Key) -> [Key:Element] where Key : Hashable {
    return elms.reduce([Key:Element]()) { (dict, elm) -> [Key:Element] in
        var dict = dict
        dict[extractKey(elm)] = elm
        return dict
    }
}
更新#2 正如Martin R所指出的,reduce将为相关闭包的每次迭代创建一个新字典。这可能会导致巨大的内存消耗

这里是
createIndex
函数的另一个版本,其中空间要求是O(n),其中n是elm的长度

func createIndex<Key, Element>(elms:[Element], extractKey:(Element) -> Key) -> [Key:Element] where Key : Hashable {
    var dict = [Key:Element]()
    for elm in elms {
        dict[extractKey(elm)] = elm
    }
    return dict
}
func-createIndex(elms:[Element],extractKey:(Element)->Key)->[Key:Element]其中Key:Hashable{
var dict=[Key:Element]()
榆树中的榆树{
dict[extractKey(elm)]=elm
}
返回指令
}

我从您的问题中了解到,您希望将
数组
转换为
字典

在我的例子中,我为
数组
创建
扩展
,字典的键将是
数组
的索引

例如:

var intArray = [2, 3, 5, 3, 2, 1]

extension Array where Element: Any {

    var toDictionary: [Int:Element] {
        var dictionary: [Int:Element] = [:]
        for (index, element) in enumerate() {
            dictionary[index] = element
        }
        return dictionary
    }

}

let dic = intArray.toDictionary
let nameLookup = persons.toDictionary{($0.name, $0)}

我想你在找这样的东西:

extension Array {
    public func toDictionary<Key: Hashable>(with selectKey: (Element) -> Key) -> [Key:Element] {
        var dict = [Key:Element]()
        for element in self {
            dict[selectKey(element)] = element
        }
        return dict
    }
}
extension Array {
    func keyBy<Key: Hashable>(_ keyFor: (Element) -> Key) -> [Key: Element] {
        var ret = [Key: Element]()
        for item in self{
            ret[keyFor(item)] = item
        }
        return ret
    }
}

如果希望代码更通用,甚至可以在
序列
上添加此扩展,而不是
数组

extension Sequence {
    public func toDictionary<Key: Hashable>(with selectKey: (Iterator.Element) -> Key) -> [Key:Iterator.Element] {
        var dict: [Key:Iterator.Element] = [:]
        for element in self {
            dict[selectKey(element)] = element
        }
        return dict
    }
}
扩展序列{
public func toDictionary(使用selectKey:(Iterator.Element)->Key)->[Key:Iterator.Element]{
变量dict:[键:迭代器.元素]=[:]
自我元素{
dict[selectKey(element)]=元素
}
返回指令
}
}

请注意,这会导致序列被迭代,在某些情况下可能会产生副作用。

此扩展适用于所有序列(包括数组),并允许您同时选择键和值:

extension Sequence {
    public func toDictionary<K: Hashable, V>(_ selector: (Iterator.Element) throws -> (K, V)?) rethrows -> [K: V] {
        var dict = [K: V]()
        for element in self {
            if let (key, value) = try selector(element) {
                dict[key] = value
            }
        }

        return dict
    }
}

在Swift 4上,您可以通过使用字典的
分组:by:
初始值设定项来实现这一点

例如: 您的类名为A

class A {

    var name: String

    init(name: String) {
        self.name = name
    }
    // .
    // .
    // .
    // other declations and implementions
}
let a1 = A(name: "Joy")
let a2 = A(name: "Ben")
let a3 = A(name: "Boy")
let a4 = A(name: "Toy")
let a5 = A(name: "Tim")

let array = [a1, a2, a3, a4, a5]
接下来,您有一个AA类型的对象数组

class A {

    var name: String

    init(name: String) {
        self.name = name
    }
    // .
    // .
    // .
    // other declations and implementions
}
let a1 = A(name: "Joy")
let a2 = A(name: "Ben")
let a3 = A(name: "Boy")
let a4 = A(name: "Toy")
let a5 = A(name: "Tim")

let array = [a1, a2, a3, a4, a5]
假设您希望通过按名称的第一个字母对所有名称进行分组来创建词典。您可以使用Swifts
字典(分组:by:)
来实现这一点

let dictionary = Dictionary(grouping: array, by: { $0.name.first! })
// this will give you a dictionary
// ["J": [a1], "B": [a2, a3], "T": [a4, a5]] 

但是请注意,生成的字典“Dictionary”是

[String : [A]]
它不是类型的

[String : A]
正如你所料。(使用
#uniquekeys with values
实现后者。)

只需简单操作

let items = URLComponents(string: "https://im.qq.com?q=13&id=23")!.queryItems!

var dic = [String: Any?]()
items.foreach {
    dic[$0.name] = $0.value
}
reduce
不是很合适

let dic: [String: Any?] = items.reduce([:]) { (result: [String: Any?], item: URLQueryItem) -> [String: Any?] in
   var r = result
   r[item.name] = item.value // will create an copy of result!!!!!!
   return r
}
是(Swift 4)吗

注意: 如注释中所述,如果您有重复的密钥,则使用
uniqueKeysWithValues
将产生致命错误(
fatal error:key'your_key'的值重复):

如果你担心这可能是你的情况,那么你可以使用


下面将数组转换为字典

let firstArray = [2,3,4,5,5] 

let dict = Dictionary(firstArray.map { ($0, 1) } , uniquingKeysWith: +)

如果您想遵循map和reduce在swift中设定的模式,您可以做一些很好且功能强大的事情,如:

extension Array {
    public func toDictionary<Key: Hashable>(with selectKey: (Element) -> Key) -> [Key:Element] {
        var dict = [Key:Element]()
        for element in self {
            dict[selectKey(element)] = element
        }
        return dict
    }
}
extension Array {
    func keyBy<Key: Hashable>(_ keyFor: (Element) -> Key) -> [Key: Element] {
        var ret = [Key: Element]()
        for item in self{
            ret[keyFor(item)] = item
        }
        return ret
    }
}
兼容Swift 5标准库(Xcode 10.2+,iOS 12.2)

下面是使用初始值设定项
init(uniqueKeysWithValues:)

输入
let array:[String]=Locale.isoRegionCodes
是由字符串表示的ISO31661-2代码组成的数组

let countryCodeAndName: [String: String] = Dictionary(uniqueKeysWithValues: Locale.isoRegionCodes.map { ($0, Locale.current.localizedString(forRegionCode: $0) ?? "")} )
返回的字典将列出所有区域,其中ISO31661-2代码作为键,本地化区域名称作为值

输出:

...
"PL":"Poland"
"DE":"Germany"
"FR":"France"
"ES":"Spain"
...
示例2:

let dictionary: [String: String] = Dictionary(uniqueKeysWithValues: [ ("key1", "value1"), ("key2", "value2")] )
输出:

["key1": "value1", "key2": "value2"]
重要提示:

前提条件:序列不能有重复的键

以下代码将使应用程序崩溃:

let digitWords = ["one", "two", "three", "four", "five", "five"]
let wordToValue = Dictionary(uniqueKeysWithValues: zip(digitWords, 1...6))
与:

致命错误:键“五”的值重复


swift5 swift4

在数组中,只有字典中的值才有键值。键应该是什么?
所以我需要创建字典
但是键应该是什么?你最初是如何得到一个数组的?如果有一个严格的格式,包含可以用作键的元素,那么应该不会太难。你能给我们看一下数组的一部分吗?我想我需要一个闭包,它传递密钥,例如类的一个成员。为了简单起见,我的第一次尝试是使用字符串键。这些键在数组中的所有元素上都是唯一的吗?如果是这样,它的计数将与数组的计数相同,那么为什么需要字典呢?是的!:-)这看起来很棒:使用reduce。我要这个。为了提高性能,模板最好使用类类型和闭包从未知成员变量传递专家密钥。请注意,这会在每个迭代步骤中创建一个新字典,因此对于大型数组来说,它可能不是最有效的解决方案有关使用
reduce
进行映射操作的一些想法,请参阅。@Peter71:我添加了
Update\1
您请求的常规函数。@MartinR:您是对的;我在
Update#2
中添加了一个更经典的方法,它的空间复杂度为O(n)。谢谢,也谢谢你。看起来
["key1": "value1", "key2": "value2"]
let digitWords = ["one", "two", "three", "four", "five", "five"]
let wordToValue = Dictionary(uniqueKeysWithValues: zip(digitWords, 1...6))
let pills = ["12", "34", "45", "67"]
let kk = Dictionary(uniqueKeysWithValues: pills.map{ ($0, "number") })

["12": "number", "67": "number", "34": "number", "45": "number"]