Swift - 利用高阶函数给字典排序

普通情况

方式一

利用 LazyMapCollection 的函式,结果为回传一个已排序好的 key 阵列。

1
public func sorted(by areInIncreasingOrder: (Element, Element) -> Bool) -> [Element]
1
2
3
4
5
6
7
8
9
10
11
12
let dictionaryData: [String : String] = ["5"  : "Five",
"6" : "Siv",
"7" : "Seven",
"1" : "One",
"2" : "Two",
"3" : "Three",
"4" : "Four",
"8" : "Eight"]

let sortedByKey = dictionaryData.keys.sorted(by: <)

print(sortedByKey) // ["1", "2", "3", "4", "5", "6", "7", "8"]

areInIncreasingOrder 这个 closure 可用 「<」 或「 >」来表示「由小排到大」或「由大排到小」。

方式二

利用 Dictionary 自有的函式,结果为回传一个已排序好的 Dictionary 阵列。

1
public func sorted(by areInIncreasingOrder: ((key: Key, value: Value), (key: Key, value: Value)) -> Bool) -> [(key: Key, value: Value)]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
let dictionaryData: [String : String] = ["5"  : "Five",
"6" : "Siv",
"7" : "Seven",
"1" : "One",
"2" : "Two",
"3" : "Three",
"4" : "Four",
"8" : "Eight"]

let sortedByKeyDictionary = dictionaryData.sorted { firstDictionary, secondDictionary in
return firstDictionary.0 < secondDictionary.0 // 由小到大排序
}

print(sortedByKeyDictionary) // [(key: "1", value: "One"), (key: "2", value: "Two"), (key: "3", value: "Three"), (key: "4", value: "Four"), (key: "5", value: "Five"), (key: "6", value: "Siv"), (key: "7", value: "Seven"), (key: "8", value: "Eight")]

第 10 行 => 该闭包所捕获的两个参数(firstDictionary, secondDictionary)为 Tuple,可以把它想像成 Dictionary 中的 Dictionary

第 11 行 => 透过 .0 来取出第1和第2个Tuple 的 key 值出来做比较。「<」表示「由小排到大」,「>」表示「由大排到小」。

第 14 行 => 结果为一 Dictionary 阵列。


Key 前缀差不多的情况

不过有时侯侯天不从人愿,后端人员把 DictionaryKey 值定义为 Item1,Item2,Item3…Item10,如果再使用原本的方法做排序,很遗憾的结果并不是我们想要的。

1
2
3
4
5
6
7
8
9
10
11
12
let dictionaryData: [String : String] = ["Item5"  : "Five",
"Item6" : "Siv",
"Item7" : "Seven",
"Item1" : "One",
"Item2" : "Two",
"Item3" : "Three",
"Item4" : "Four",
"Item9" : "Nine",
"Item10" : "Ten",
"Item8" : "Eight"]

let sortedData = dictionaryData.keys.sorted(by: <) // ["Item1", "Item10", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9"]

结果为:Item1、Item10、Item2 … Item9。

那我们该怎么办呢?其实不难,我们可以取 Item 之后的字串再转成 Int 后来做比较即可,用以上的两种方式再合并修改一下写法即可。

方式一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let dictionaryData: [String : String] = ["Item5"  : "Five",
"Item6" : "Siv",
"Item7" : "Seven",
"Item1" : "One",
"Item2" : "Two",
"Item3" : "Three",
"Item4" : "Four",
"Item9" : "Nine",
"Item10" : "Ten",
"Item8" : "Eight"]

let sortedData = dictionaryData.keys.sorted(by: { firstKey, secondKey in
let key1Index = firstKey.index(firstKey.startIndex, offsetBy: 4) // 取 Item 字串後的值出來做排序
let key1 = Int(firstKey.substring(from: key1Index)) // 5

let key2Index = secondKey.index(secondKey.startIndex, offsetBy: 4) // 取 Item 字串後的值出來做排序
let key2 = Int(secondKey.substring(from: key2Index)) // 6

return key1! < key2! // 由小到大排序
})

print(sortedData) // ["Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9", "Item10"]

第 13~14 行 => 将 Item 字串后的值取出后并转成 Int。

结果为: [“Item1”, “Item2”, “Item3”, “Item4”, “Item5”, “Item6”, “Item7”, “Item8”, “Item9”, “Item10”]。

方式二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
let dictionaryData: [String : String] = ["Item5"  : "Five",
"Item6" : "Siv",
"Item7" : "Seven",
"Item1" : "One",
"Item2" : "Two",
"Item3" : "Three",
"Item4" : "Four",
"Item9" : "Nine",
"Item10" : "Ten",
"Item8" : "Eight"]

let sortedByKeyDictionary = dictionaryData.sorted { firstDictionary, secondDictionary in
let firstKey = firstDictionary.0 // Item5
let firstKeyIndex = firstKey.index(firstKey.startIndex, offsetBy: 4) // 取 Item 字串後的值出來做排序
let firstKeyRealValue = Int(firstKey.substring(from: firstKeyIndex)) // 10

let secondKey = secondDictionary.0 // Item6
let secondKeyIndex = secondKey.index(secondKey.startIndex, offsetBy: 4) // 取 Item 字串後的值出來做排序
let secondKeyRealValue = Int(secondKey.substring(from: secondKeyIndex)) // 5
return firstKeyRealValue! < secondKeyRealValue! // 由小到大排序
}

print(sortedByKeyDictionary) // [(key: "Item1", value: "One"), (key: "Item2", value: "Two"), (key: "Item3", value: "Three"), (key: "Item4", value: "Four"), (key: "Item5", value: "Five"), (key: "Item6", value: "Siv"), (key: "Item7", value: "Seven"), (key: "Item8", value: "Eight"), (key: "Item9", value: "Nine"), (key: "Item10", value: "Ten")]

第 13 行 => 取出 Tuple 的第 0 个 index 值的资料,也就是 Dictionary Key。

结果为:[(key: “Item1”, value: “One”), (key: “Item2”, value: “Two”), (key: “Item3”, value: “Three”), (key: “Item4”, value: “Four”), (key: “Item5”, value: “Five”), (key: “Item6”, value: “Siv”), (key: “Item7”, value: “Seven”), (key: “Item8”, value: “Eight”), (key: “Item9”, value: “Nine”), (key: “Item10”, value: “Ten”)]。

------本文结束 感谢阅读------

本文地址:https://www.kaaaaai.cn/swift-use-higher-orderfunctions-to-dictionary-sort.html
本文基于 知识共享署名-相同方式共享 4.0 国际许可协议发布
转载请注明出处,谢谢!

众筹项目:拯救世界!
0%