sort array of dictionaries

How do I sort an array of dictionary objects based on the value of the dictionary? I understand I should use the sorted method of the array, but I don't understand the notation that uses $0.1 and $0.0. Where is the documentation on that?

I need to make a correction. I actually just need to sort a dictionary by its key or it's key or it's value.

Dictionary can hold multiple different keys. If you show an example Array of Dictionary and expected result, there are many who can show your an example code.

Example:


var dict: [String:String] = ["tmomail.net":"T-Mobile", "message.alltel.com":"Alltel", "messaging.nextel.com":"Nextel"]


Expected result:


print(dict)

[ "message.alltel.com" : "Alltel", "messaging.nextel.com" : "Nextel", "tmomail.net" : "T-Mobile"]

The values are alphabetized, not the keys.

Example:

var dict: [String:String] = ["tmomail.net":"T-Mobile", "message.alltel.com":"Alltel", "messaging.nextel.com":"Nextel"]


Unfortunately, it's a single Dictionary, not an Array of Dictionary. And in Swift, Dictionary is an unordered hash map based collection. The result of `print(dict)` is unpredictable and cannot be controlled.


Printing out the contents may not be your actual purpose. Please explain how you want to utilized the sorted result.

It's complicated. I need to to present a list of cellular providers in a picker view. I want the picker view to show the title of the provider in alphabetical order. A title would be, for instance, "AT&T" - what the user will see as the provider. I need to save the list of providers in Core Data. Each provider has a unique provider id. Each provider also needs to have a unique index so that when I show the provider in picker view, the row variable in pickerView(_:didSelectRow:_:) matches the index of the provider. The provider id is used to identify the provider for recipients kept in another entity of Core Data. Each provider has a domain. The domain is used to send an email to the provider, and the provider relays the message in the email to a text message. The email address would be the ten-digit number an @ character and the domain. For instance, 9031112222@txt.att.net would be sent to AT&T and they would relay the message by text to the phone number (903) 111-2222. I need to be able to sort the titles of the providers alphabetically and yet still associate the domain of each provider with the title. I need the index of the provider to be in the same order as the title, so that if the first title in the alphabetical list is "Alltel", then the index would be 0, and the next title alphabetically would be "Nextel", then the index would be one. The index and the title would both be in order.


Perhaps I need three arrays. One for the id, one for the domain and the other for the title. The id and the domain and the title can be matched to each other because they have the same index.


I could create an object to represent each provider with properties for id, domain and title. Then I would put the providers in an array.


let providers: [Provider] = []


In this case, how would I sort the array by the title property?

$0 means the element of the dict

$0.0 is the first component (the key) and $0.1 the second(the content)


you can also use $0.key and $0.value instead.


Here is how to sort on value, descending ; if value equal, by ascending key:

let sortedByValueArray = dict.sorted(by: {
    if $0.value != $1.value { return $0.value > $1.value } else { return String(describing: $0.key) < String(describing: $1.key) } })


This is equivalent to

let keyValueArray = dict.sorted(by: {
    if $0.1 != $1.1 { return $0.1 > $1.1 } else { return String(describing: $0.0) < String(describing: $1.0) } })


If you just want to get values in an array, apply flatMap:

let sortedByValueArray = dict.sorted(by: {
    if $0.value != $1.value { return $0.value > $1.value } else { return String(describing: $0.key) < String(describing: $1.key) } }).flatMap{ $0.1 }

or

let keyValueArray = dict.sorted(by: {
    if $0.1 != $1.1 { return $0.1 > $1.1 } else { return String(describing: $0.0) < String(describing: $1.0) } }).flatMap{ $0.value }


look here for a detailed discussion

h ttps://stackoverflow.com/questions/33882057/swift-sort-dictionary-keys-by-value-then-by-key

I could create an object to represent each provider with properties for id, domain and title. Then I would put the providers in an array.


It seems to be a far better idea.


In this case, how would I sort the array by the title property?


With given an Array of some type, sorting is not so difficult.


An example:

struct Provider {
    var id: Int
    var domain: String
    var title: String
}

//Useful for debugging...
extension Provider: CustomStringConvertible {
    var description: String {
        return "Provider(\(id),\(domain),\(title))"
    }
}

let providers: [Provider] = [
    Provider(id: 1, domain: "tmomail.net", title: "T-Mobile"),
    Provider(id: 2, domain: "message.alltel.com", title: "Alltel"),
    Provider(id: 3, domain: "messaging.nextel.com", title: "Nextel"),
]

let sortedByDomain = providers.sorted {$0.domain < $1.domain}
print(sortedByDomain)
//->[Provider(2,message.alltel.com,Alltel), Provider(3,messaging.nextel.com,Nextel), Provider(1,tmomail.net,T-Mobile)]

let sortedByTitle = providers.sorted {$0.title < $1.title}
print(sortedByTitle)
//->[Provider(2,message.alltel.com,Alltel), Provider(3,messaging.nextel.com,Nextel), Provider(1,tmomail.net,T-Mobile)]

Arrays sort

---------------

a.sort(by: <)

a.sort(by: >)

You can create a function which returns a Bool. Here's a simple example.

let dict1 = ["Name" : "Wanda", "Age" : 32, "Gender" : "Female"] as [String : Any]
let dict2 = ["Name" : "John", "Age" : 25, "Gender" : "Male"] as [String : Any]
let dict3 = ["Name" : "Bob", "Age" : 15, "Gender" : "Male"] as [String : Any]
let dict4 = ["Name" : "Jane", "Age" : 50, "Gender" : "Female"] as [String : Any]
let dict5 = ["Name" : "Bill", "Age" : 75, "Gender" : "Female"] as [String : Any]

var dictArray = [dict5, dict3, dict1, dict4, dict2]

func dictSort(dict1: [String: Any], dict2: [String: Any]) -> Bool {
    guard let i0 = dict1["Age"] as? Int,
          let i1 = dict2["Age"] as? Int else {return false}

    return i0 < i1
}

var sortedArray = dictArray.sorted{dictSort(dict1: $0, dict2: $1)}
sort array of dictionaries
 
 
Q