Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort Dictionary by Key Value

Tags:

sorting

swift

let dict: [String:Int] = ["apple":5, "pear":9, "grape":1]

How do you sort the dictionary based on the Int value so that the output is:

sortedDict = ["pear":9, "apple":5, "grape":1]

Current Attempt (doesn't sort correctly):

let sortedDict = sorted(dict) { $0.1 > $1.1 } 
like image 973
Onichan Avatar asked Jul 20 '15 23:07

Onichan


2 Answers

You need to sort your dictionary values, not your keys. You can create an array of tuples from your dictionary sorting it by its values as follow:

Xcode 9 • Swift 4 or Xcode 8 • Swift 3

let fruitsDict = ["apple": 5, "pear": 9, "grape": 1]
let fruitsTupleArray = fruitsDict.sorted{ $0.value > $1.value }

fruitsTupleArray // [(.0 "pear", .1 9), (.0 "apple", .1 5), (.0 "grape", .1 1)]

for (fruit,votes) in fruitsTupleArray {
    print(fruit,votes)
}

fruitsTupleArray.first?.key   // "pear"
fruitsTupleArray.first?.value   // 9

To sort your dictionary using your keys

let fruitsTupleArray = fruitsDict.sorted{ $0.key > $1.key }
fruitsTupleArray  // [(key "pear", value 9), (key "grape", value 1), (key "apple", value 5)]

To sort your dictionary using its keys and localized comparison:

let fruitsTupleArray = fruitsDict.sorted { $0.key.localizedCompare($1.key) == .orderedAscending  }

edit/update:

We can also extend Sequence protocol and implement a custom sort that takes a predicate and sort using a keypath property as long as it conforms to Comparable:

extension Sequence {
    func sorted<T: Comparable>(_ predicate: (Element) -> T, by areInIncreasingOrder: ((T,T)-> Bool) = (<)) -> [Element] {
        sorted(by: { areInIncreasingOrder(predicate($0), predicate($1)) })
    }
}

Usage:

let sortedFruitsAscending = fruitsDict.sorted(\.value)
print(sortedFruitsAscending)

let sortedFruitsDescending = fruitsDict.sorted(\.value, by: >)
print(sortedFruitsDescending)

This will print

[(key: "grape", value: 1), (key: "apple", value: 5), (key: "pear", value: 9)]

[(key: "pear", value: 9), (key: "apple", value: 5), (key: "grape", value: 1)]


edit/update:

For Xcode 13 or later you can use a new generic structure called KeyPathComparator:

let fruitsTupleArray = fruitsDict.sorted(using: KeyPathComparator(\.value, order: .reverse))
like image 110
Leo Dabus Avatar answered Oct 21 '22 14:10

Leo Dabus


Dictionaries can't be sorted. Generally, when I need things sorted from a dictionary, I will make a separate array of my dictionary keys.

In your case, make an array of the keys, sort them by comparing their values in the dictionary.

like image 40
boboguitar Avatar answered Oct 21 '22 13:10

boboguitar