【发布时间】:2016-01-23 20:38:51
【问题描述】:
我有一个字典,我需要从中派生一个键数组和一个值数组,该数组按键或值排序。
我的用例是一个文件夹列表。字典包含文件夹名称(键)和文件夹中的项目数(值)。我想按键名(A 到 Z 或 Z 到 A)以及计数大小(从大到小或从小到大)进行排序。
在 Swift 中对键进行排序很容易。但我诉诸迭代来提供排序的值列表。这看起来不像 Swift 做事的方式,但我对 Swift 中的 map / sort / etc. 的理解还不够好,无法让我看到更聪明的方式。
谁能解释一个聪明而简洁的 Swift 方法来实现这个目标?
我当前的代码是:
let dictionary = ["Alpha" : 24, "Beta" : 47, "Gamma" : 12, "Delta" : 33]
enum FolderOrder : Int {
case AlphaAtoZ
case AlphaZtoA
case SizeLargeToSmall
case SizeSmallToLarge
}
func folderList(fromDictionary: [String: Int], orderedBy : FolderOrder = .AlphaAtoZ) -> [String] {
switch orderedBy {
case .AlphaAtoZ:
return fromDictionary.keys.sort() {$0 < $1}
case .AlphaZtoA:
return fromDictionary.keys.sort() {$1 < $0}
case .SizeSmallToLarge:
return fromDictionary.keys.sort(){fromDictionary[$0] < fromDictionary [$1]}
case .SizeLargeToSmall:
return fromDictionary.keys.sort(){fromDictionary[$1] < fromDictionary [$0]}
}
}
func folderCounts(fromDictionary: [String: Int], orderedBy : FolderOrder = .AlphaAtoZ) -> [Int]
{
let orderedKeys = folderList(fromDictionary, orderedBy: orderedBy)
var orderedValues = [Int]()
for key in orderedKeys {
orderedValues.append(fromDictionary[key] ?? 0)
}
return orderedValues
}
folderList(dictionary, orderedBy: .AlphaAtoZ)
// ["Alpha", "Beta", "Delta", "Gamma"]
folderList(dictionary, orderedBy: .AlphaZtoA)
// ["Gamma", "Delta", "Beta", "Alpha"]
folderList(dictionary, orderedBy: .SizeSmallToLarge)
// ["Gamma", "Alpha", "Delta", "Beta"]
folderList(dictionary, orderedBy: .SizeLargeToSmall)
//["Beta", "Delta", "Alpha", "Gamma"]
folderCounts(dictionary, orderedBy: .AlphaAtoZ)
// [24, 47, 33, 12]
folderCounts(dictionary, orderedBy: .SizeLargeToSmall)
// [47, 33, 24, 12]
更新
感谢两个有用的答案,尤其是@nRewik,我简化了我的代码并提高了我对 Swift 的理解。
修改后的代码,用 cmets 拼出我最初不清楚的内容,因此可能对其他人有所帮助:
let dictionary = ["Alpha" : 24, "Beta" : 47, "Gamma" : 12, "Delta" : 33]
enum FolderOrder {
case AlphaAtoZ
case AlphaZtoA
case SizeLargeToSmall
case SizeSmallToLarge
}
func folderListAndCounts(fromDictionary: [String: Int], orderedBy : FolderOrder = .AlphaAtoZ) -> ([String], [Int]) {
var sortedDictionary : [(String, Int)]
switch orderedBy {
// The closure when sort() is applied to a dictionary takes two tuples as parameters
// where the tuples are of the form (key, value). The first tuple can be accessed as $0.
// Its key can be accessed as $0.0 and its value as $0.1
case .AlphaAtoZ:
sortedDictionary = fromDictionary.sort{ $0.0 < $1.0 } // item(n).key < item(n+1).key
case .AlphaZtoA:
sortedDictionary = fromDictionary.sort{ $0.0 > $1.0 } // item(n).key > item(n+1).key
case .SizeSmallToLarge:
sortedDictionary = fromDictionary.sort{ $0.1 < $1.1 } // item(n).value < item(n+1).value
case .SizeLargeToSmall:
sortedDictionary = fromDictionary.sort{ $0.1 > $1.1 } // item(n).value < item(n+1).value
}
// The sorted dictionary has the type: [(String, Int)], i.e. it's an array of tuples.
// The closure when map is applied to an array of tuples is a tuple. The tuple can be
// accessed as $0. Its key can be accessed as $0.0 and its value as $0.1
let sortedKeys = sortedDictionary.map{$0.0}
let sortedValues = sortedDictionary.map{$0.1}
// Returns a tuple (arrayOfKeys, arrayOfValues)
return (sortedKeys, sortedValues)
}
let (keys, counts) = folderListAndCounts(dictionary, orderedBy: .SizeSmallToLarge)
【问题讨论】:
标签: arrays swift sorting dictionary