Sort Dictionary by values in Swift
Try:
let dict = ["a":1, "c":3, "b":2]
extension Dictionary {
func sortedKeys(isOrderedBefore:(Key,Key) -> Bool) -> [Key] {
return Array(self.keys).sort(isOrderedBefore)
}
// Slower because of a lot of lookups, but probably takes less memory (this is equivalent to Pascals answer in an generic extension)
func sortedKeysByValue(isOrderedBefore:(Value, Value) -> Bool) -> [Key] {
return sortedKeys {
isOrderedBefore(self[$0]!, self[$1]!)
}
}
// Faster because of no lookups, may take more memory because of duplicating contents
func keysSortedByValue(isOrderedBefore:(Value, Value) -> Bool) -> [Key] {
return Array(self)
.sort() {
let (_, lv) = $0
let (_, rv) = $1
return isOrderedBefore(lv, rv)
}
.map {
let (k, _) = $0
return k
}
}
}
dict.keysSortedByValue(<)
dict.keysSortedByValue(>)
Updated:
Updated to the new array syntax and sort semantics from beta 3. Note that I'm using sort
and not sorted
to minimize array copying. The code could be made more compact, by looking at the earlier version and replacing sort
with sorted
and fixing the KeyType[]
to be [KeyType]
Updated to Swift 2.2:
Changed types from KeyType
to Key
and ValueType
to Value
. Used new sort
builtin to Array
instead of sort(Array)
Note performance of all of these could be slightly improved by using sortInPlace
instead of sort
Sort dictionary by value in swift
In the comments, you specified that you want to sort the value arrays. You can accomplish this using mapValues
and sorted
like this:
let sortedResult = plistdata.mapValues { $0.sorted() }
Note: Dictionaries in Swift are unordered (have no specified order), so it isn't possible to put the keys into a specific order. If you'd like to display the keys in a specific sorted order, then sort them into a separate array using let sortedKeys = plistdata.keys.sorted()
.
Swift sort dictionary by value
It is not clear what your expectations are. There is really no such thing as a sorted dictionary. Your code is basically correct except for a misplaced parenthesis. I tried this:
let d = ["Museum1":8785.8971799638,
"Museum2":34420.9643422388,
"Museum3":826.467789130732,
"Museum4":304120.342151219]
for (k,v) in (Array(d).sorted {$0.1 < $1.1}) {
println("\(k):\(v)")
}
Result:
Museum3:826.467789130732
Museum1:8785.8971799638
Museum2:34420.9643422388
Museum4:304120.342151219
If you think that's wrong, you need to explain why.
Swift: How to sort a dictionary by value, but the value is a tuple?
Dictionaries are not ordered and can't be sorted directly but you can sort the content which will give you an array of key value tuples. Then this array can be mapped to an array of keys which can be used to access the dictionary in a sorted fashion.
This will sort by the second value in the tuple and return an array of keys
let sorttedKeys = dict.sorted(by: { $0.value.1 < $1.value.1}).map {$0.key}
sorttedKeys.forEach {
print("\($0): \(dict[$0]!)")
}
b: (9, 1)
a: (3, 2)
c: (4, 3)
How to sort dictionary by value?
So if I take your example, this does the trick:
var items = [Int: [String]]()
items[0] = ["Apple","/image/apple.png","29"]
items[1] = ["AAA","/image/aaa.png","29"]
items[2] = ["Banana","/image/banana.png","29"]
let itemResult = items.sorted { (first: (key: Int, value: [String]), second: (key: Int, value: [String])) -> Bool in
return first.value.first! < second.value.first!
}
print (itemResult)
The right thing to do is to use objects of course, and note that I'm not null checking the "first" object in each array, but this is not a problem to change.
Let me know if this is what you were looking for, the output is:
[(1, ["AAA", "/image/aaa.png", "29"]), (0, ["Apple", "/image/apple.png", "29"]), (2, ["Banana", "/image/banana.png", "29"])]
EDIT:
Also note, that this case doesn't actually "sort" the dictionary, because a dictionary is by definition not sorted, this creates an array of key-value objects sorted using the array indexes
Sort Dictionary [Key: [Key: Value]] by value - Swift
A Dictionary
is unordered by design, as the documentation clearly states:
Every dictionary is an unordered collection of key-value pairs.
You are probably looking for an ordered type like Array
.
var arrayDict = [
["nausea": 23, "other": "hhh"],
["nausea": 3, "other": "kkk"],
["nausea": 33, "other" : "yyy"]
]
let sorted = arrayDict.sorted { $0["nausea"] as! Int < $1["nausea"] as! Int }
print(sorted)
Update: Even better as @LeoDabus suggested in the comment you can use an array of custom objects:
struct MyObject {
var nausea: Int
var other: String
}
var array = [
MyObject(nausea: 23, other: "hhh"),
MyObject(nausea: 3, other: "kkk"),
MyObject(nausea: 33, other: "yyy")
]
let sorted = array.sorted { $0.nausea < $1.nausea }
print(sorted)
Sort Dictionary by keys
let dictionary = [
"A" : [1, 2],
"Z" : [3, 4],
"D" : [5, 6]
]
let sortedKeys = Array(dictionary.keys).sorted(<) // ["A", "D", "Z"]
EDIT:
The sorted array from the above code contains keys only, while values have to be retrieved from the original dictionary. However, 'Dictionary'
is also a 'CollectionType'
of (key, value) pairs and we can use the global 'sorted'
function to get a sorted array containg both keys and values, like this:
let sortedKeysAndValues = sorted(dictionary) { $0.0 < $1.0 }
println(sortedKeysAndValues) // [(A, [1, 2]), (D, [5, 6]), (Z, [3, 4])]
EDIT2: The monthly changing Swift syntax currently prefers
let sortedKeys = Array(dictionary.keys).sort(<) // ["A", "D", "Z"]
The global sorted
is deprecated.
Sort dictionary by keys in Swift
Dictionary
already has a sorted
method that takes a closure that defines the sorting function. You can sort by keys in the closure, then simply map over the resulting tuples to get the values only.
let sortedDictKeys = dict.sorted(by: { $0.key < $1.key }).map(\.value)
Sorting Dictionary on two values in swift
Dictionaries are unordered collections and you can't sort them.
However, you can use .sorted(by:)
method that returns a list of ordered tuples where each one represents a key-value entry in the dictionary:
dictionary.sorted { (lhs, rhs) -> Bool in
if (lhs.value["Page"]! == rhs.value["Page"]!) {
return lhs.value["Position"]! < rhs.value["Position"]!
} else {
return lhs.value["Page"]! < rhs.value["Page"]!
}
}
which results in sth like below:
[(key: "FOSCI012", value: ["Position": 1, "Page": 1]),
(key: "COSNAI423", value: ["Position": 2, "Page": 1]),
...
(key: "TOORL002B", value: ["Position": 1, "Page": 2]),
(key: "CGLYN188", value: ["Position": 2, "Page": 2]),
...
]
Here you can download the playground.
Related Topics
Swift - Reorder Uitableview Cells
Extend Generic Array<T> to Adopt Protocol
How to Call the More Specific Method of Overloading
Fblpromises Framework Not Found
Most Efficient Way to Access Multi-Dimensional Arrays in Swift
Many Ways of Defining a Swift Dictionary
Error: Binary Operator '<=' Cannot Be Applied to Operands of Type 'Int' and 'Int'
Does the Order of Subscribeon and Observeon Matter
Appearance Proxies/Ui_Appearance_Selector in Swift
iOS 13: Threading Violation: Expected the Main Thread
How to Make Cells Have a Gradient Background
What Would Be a Proper Storyboard Example of Combining Nav Bars and Tab Bars in One App
Swiftui: How to Make Entire Shape Recognize Gestures When Stroked
Swift Struct Initialization, Making Another Struct Like String