按键排序字典

164

我想在Swift中对一个字典进行排序。 我有一个类似于以下的字典:

"A" => Array[]
"Z" => Array[]
"D" => Array[]

等等,我希望它像这样

"A" => Array[]
"D" => Array[]
"Z" => Array[]

我在 Stack Overflow 上尝试了许多解决方案,但没有一个适用于我。我正在使用 XCode6 Beta 5,在它上面有些方法会出现编译错误,有些解决方案会引发异常。所以,如果有人能够发布一个可用的字典排序代码,请帮忙。


10
字典是一种关联容器,无法对其进行排序。如果需要特定顺序,请将键复制到数组中并对其进行排序。然后迭代键,并获取相应的值。 - Sergey Kalinichenko
@dasblinkenlight,你能告诉我如何在Swift中对数组进行排序吗? - Aleem Ahmad
@dasblinkenlight 我已经尝试过了,但是在 [KeyType] 上出现了错误。 - Aleem Ahmad
@AleemAhmad 这是因为您需要将 KeyType 替换为您特定字典中键的类型(看起来您正在使用字符串)。 - Sergey Kalinichenko
显示剩余3条评论
16个回答

200
let dictionary = [
    "A" : [1, 2],
    "Z" : [3, 4],
    "D" : [5, 6]
]

let sortedKeys = Array(dictionary.keys).sorted(<) // ["A", "D", "Z"]

编辑:

上述代码中的排序数组仅包含键,而值必须从原始字典中检索。然而,'Dictionary' 也是一个 (key, value) 对的 'CollectionType',我们可以使用全局的 'sorted' 函数来获取一个包含键和值的排序数组,如下所示:

let sortedKeysAndValues = sorted(dictionary) { $0.0 < $1.0 }
print(sortedKeysAndValues) // [(A, [1, 2]), (D, [5, 6]), (Z, [3, 4])]

编辑2:目前每月变化的Swift语法更倾向于

let sortedKeys = Array(dictionary.keys).sort(<) // ["A", "D", "Z"]

全局变量 sorted 已经被弃用。


3
这将给你一个键的数组。该数组缺少值。我猜你可以从字典中查找值。 - StilesCrisis
2
你说得对。我刚刚编辑了帖子,提供了一个按键排序的(键,值)对数组解决方案。感谢您的评论。 - Ivica M.
@IvicaM。你好!我明白如何按键对字典进行排序,但我不明白如何对字典中的元素数组进行排序。请帮帮我。例如:private var contacts: [(String, [User])] = []。 - Alexander Khitev
6
Swift 3 = Array(dictionary.keys).sorted(by: <) - miff
12
从 Swift 4 开始,你可以写成 let sortedKeys = dictionary.keys.sorted() 来获取已排序的字典键。 - Code Different
2
由于这里有很多重复的事情,值得一提的是,现在在swift-collections中有OrderedDictionary。https://github.com/apple/swift-collections/blob/main/Documentation/OrderedDictionary.md - Rob Napier

139

明确一点,您无法对字典进行排序。但是您可以输出一个可排序的数组。

Swift 2.0

Ivica M的回答已更新:

let wordDict = [
     "A" : [1, 2],
     "Z" : [3, 4],
     "D" : [5, 6]
]

let sortedDict = wordDict.sort { $0.0 < $1.0 }
print("\(sortedDict)") // 

Swift 3

wordDict.sorted(by: { $0.0 < $1.0 })

38
实际上,它返回的是一个[(String, [Int])]数组而不是一个字典。 - scord
4
我理解到词典是无序的,因此重新创建这种数据类型并没有太多意义。最终我只是保存了一个已排序键的数组。 - scord
我得到了“二进制运算符>不能与两个Any操作数进行比较。向下转换也不起作用。” - Sean

38

Swift 5 中,按键对字典进行排序

let sortedYourArray = YOURDICTIONARY.sorted( by: { $0.0 < $1.0 })

为了按值对字典进行排序

let sortedYourArray = YOURDICTIONARY.sorted( by: { $0.1 < $1.1 })

5
请注意,这会返回一个按字典元素排序的数组。您可以像处理字典一样循环遍历它,例如 for (key, value) in sortedDictArray { } - vomi

36
如果您想按键排序顺序迭代键和值,那么这种形式非常简洁。
let d = [
    "A" : [1, 2],
    "Z" : [3, 4],
    "D" : [5, 6]
]

Swift 1,2:

for (k,v) in Array(d).sorted({$0.0 < $1.0}) {
    print("\(k):\(v)")
}

Swift 3+:

for (k,v) in Array(d).sorted(by: {$0.0 < $1.0}) {
    print("\(k):\(v)")
}

sorted是自定义方法还是系统方法?在实现时出现了错误。 - rikky
@rikkyG Swift 1: sortsorted。Swift 2: sort 已经变成了 sortInPlace,而 sorted 变成了 sort - Eric Aya

29

我试过上面列举的所有方法,总之你所需要的就是

let sorted = dictionary.sorted { $0.key < $1.key }
let keysArraySorted = Array(sorted.map({ $0.key }))
let valuesArraySorted = Array(sorted.map({ $0.value }))

太棒了,首先进行排序,然后获取所有的键和值。由于键和值相同,因此顺序不能互换。谢谢! - Yogesh Patel

16

在 Swift 4 中,您可以更加智能地编写它:

let d = [ 1 : "hello", 2 : "bye", -1 : "foo" ]
d = [Int : String](uniqueKeysWithValues: d.sorted{ $0.key < $1.key })

3
谢谢您的努力,但首先,“let”不能使代码成功编译,所以需要更改为“var”。 然后,在编译成功后,此代码没有按字典键排序,运行前后结果相同。 也许我漏掉了什么,请详细说明或更改代码。原始代码:var d = [ 1 : "hello", 2 : "bye", -1 : "foo" ] print(d) ->>> prints [2: "bye", -1: "foo", 1: "hello"] d = [Int : String](uniqueKeysWithValues: d.sorted{ $0.key < $1.key }) print(d) ->>> prints [2: "bye", -1: "foo", 1: "hello"] - KarimIhab
不可能的,因为当你将它转换回字典时,它会变成无序集合,因为Swift中的字典是无序集合。 - Jaimin

12

Swift 4 & 5

用于字符串键排序:

dictionary.keys.sorted(by: {$0.localizedStandardCompare($1) == .orderedAscending})

例子:

var dict : [String : Any] = ["10" : Any, "2" : Any, "20" : Any, "1" : Any]

dictionary.keys.sorted() 

["1" : 任意, "10" : 任意, "2" : 任意, "20" : 任意]

dictionary.keys.sorted(by: {$0.localizedStandardCompare($1) == .orderedAscending})

["1":任意, "2":任意, "10":任意, "20":任意]


8

Swift 5

输入您想按键字母顺序排序的字典。

// Sort inputted dictionary with keys alphabetically.
func sortWithKeys(_ dict: [String: Any]) -> [String: Any] {
    let sorted = dict.sorted(by: { $0.key < $1.key })
    var newDict: [String: Any] = [:]
    for sortedDict in sorted {
        newDict[sortedDict.key] = sortedDict.value
    }
    return newDict
}

dict.sorted(by: { $0.key < $1.key })本身返回一个元组(value, value),而不是一个字典[value: value]。因此,for循环解析元组并将其返回为字典。这样,您可以放入一个字典并获得一个字典。


1
字典无法排序,因为它包含可哈希映射。 - mazy
不要为我尝试。 var dict = ["Alise": [1,3,2], "Jane": [2,5], "Dany": [1]] let sorted = sortWithKeys(dict) 它返回["Dany": [1], "Alise": [1, 3, 2], "Jane": [2, 5]],因为字典与排序无关。 但是sortedBy返回"[(key: "Alise", value: [1, 3, 2]), (key: "Dany", value: [1]), (key: "Jane", value: [2, 5])]\n"。 - mazy
2
当您创建一个新的字典时,如何保证它是有序的? - hariszaman
创建新的字典时,您只需设置键和值,因此顺序不会得到尊重。 - Pau Senabre

7

对于Swift 4,以下内容适用:

let dicNumArray = ["q":[1,2,3,4,5],"a":[2,3,4,5,5],"s":[123,123,132,43,4],"t":[00,88,66,542,321]]

let sortedDic = dicNumArray.sorted { (aDic, bDic) -> Bool in
    return aDic.key < bDic.key
}

10
这不会返回一个字典,而是会返回一个元组数组。 - Daniel Arantes Loverde
@DanielArantesLoverde 字典本质上是无法排序的。元组数组是你能做到的最好的选择。 - John Montgomery
2
我知道,但问题要求有序,所以这个答案是不正确的。你同意吗? - Daniel Arantes Loverde

7
这是一种优雅的替代方案,可以避免对字典本身进行排序:
自Swift 4和5起:
let sortedKeys = myDict.keys.sorted()

for key in sortedKeys {
   // Ordered iteration over the dictionary
   let val = myDict[key]
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接