简体   繁体   中英

Swift 4 sort dictionary by the first value

I'm working on an iOS app using Swift 4 and I have a dictionary like this:

var list = [
"US" : ["United-States","$"], 
"FR" : ["France","€"],
"CN" :["China", "¥"]
]

I would like to sort a UITableView based on this dictionary by the first value of each key in order to get the following result:

China
France
United-States

This this possible?

You can get your dictionary values (arrays), map their first element and sort it:

let list = ["US" : ["United-States","$"],
            "FR" : ["France","€"],
            "CN" : ["China", "¥"]]

let countries = list.values.compactMap{$0.first}.sorted()

print(countries)    // ["China", "France", "United-States"]

Another options is to create a struct for your currency, create a custom initializer that takes a key value pair and make it conform to Comparable protocol:

struct Currency: CustomStringConvertible, Comparable {
    let name: String
    let code: String
    let symbol: String
    init?(currency: (key: String, value: [String])) {
        guard currency.value.count == 2 else { return nil }
        self.code = currency.key
        self.name = currency.value.first!
        self.symbol = currency.value.last!
    }

    var description: String {
        return "Code: \(code)\nName: \(name)\nSynmbol: \(symbol)\n"
    }
}
extension Currency {
    static func <(lhs: Currency, rhs: Currency) -> Bool {
        return lhs.name < rhs.name
    }
}

let list = ["US" : ["United-States","$"],
            "FR" : ["France","€"],
            "CN" :["China", "¥"]]

let currencies = list.compactMap(Currency.init).sorted()
currencies.map({print($0)})

This will print:

Code: CN

Name: China

Synmbol: ¥

Code: FR

Name: France

Synmbol: €

Code: US

Name: United-States

Synmbol: $

Use map to create an array of tuples with your country's symbol , name , and currency , and then sort that array by name :

let list = ["US" : ["United-States","$"],
            "FR" : ["France","€"],
            "CN" : ["China", "¥"]]

let newlist = list.map { (symbol: $0.key, name: $0.value.first ?? "", currency: $0.value.dropFirst().first ?? "")}.sorted { $0.name < $1.name }

print(newlist)

[(symbol: "CN", name: "China", currency: "¥"), (symbol: "FR", name: "France", currency: "€"), (symbol: "US", name: "United-States", currency: "$")]

This will allow you to access all of the information easily for your table:

let symbol = newlist[indexPath.row].symbol
let name = newlist[indexPath.row].name
let currency = newlist[indexPath.row].currency

or just:

let (symbol, name, currency) = newlist[indexPath.row]

For your more complicated dictionary...

One of your problems is that your value is now [Any] , so conditional casts are needed. Also, break up creation of the newlist and the sorting.

let list = ["US" : ["United-States","$","My comment", 10],
            "FR" : ["France","€", "My super comment", 20],
            "CA" : ["Canada","$", "Whatever", 15],
            "CN" : ["China", "¥", "Final comment", 5]]

let newlist = list.map { (symbol: $0.key,
                          name: $0.value.first as? String ?? "",
                          currency: $0.value.dropFirst().first as? String ?? "",
                          comment: $0.value.dropFirst(2).first as? String ?? "",
                          value: $0.value.dropFirst(3).first as? Int ?? 0) }

let sortedlist = newlist.sorted { $0.name < $1.name }
print(sortedlist)

[(symbol: "CA", name: "Canada", currency: "$", comment: "Whatever", value: 15), (symbol: "CN", name: "China", currency: "¥", comment: "Final comment", value: 5), (symbol: "FR", name: "France", currency: "€", comment: "My super comment", value: 20), (symbol: "US", name: "United-States", currency: "$", comment: "My comment", value: 10)]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM