3
var arr:Array<Dictionary<String, String>> = [["title":"Mrs","name":"Abc"],["title":"Mr","name":"XYZ"]]
arr.sort { (<#[String : String]#>, <#[String : String]#>) -> Bool in
        <#code#>
    }

I have an array of dictionaries with the data format as represented above. I want to sort this array by name key. I did it in older swift like:

arr.sort{$0.name < $1.name}

which is not working anymore. Please let me know how to move ahead with this structure and sort it.

Thanks.

3
  • 4
    Am I the only one who is thinking about "@MartinR is coming!!"? :) Commented Dec 5, 2016 at 11:18
  • 2
    Dot notation does not work in older swift either. Commented Dec 5, 2016 at 11:19
  • I agree, can't see when it can work. I would use if let to catch name value, but if you want something short arr.sorted { $0["name"]! < $1["name"]! } Commented Dec 5, 2016 at 11:22

2 Answers 2

5

You have an array of dictionaries of the form [String: String] and a dictionary does not have a name property, so $0.name is invalid (in any Swift version).

Retrieving the dictionary value is done via subscripting, e.g. $0["name"], which returns an optional. In Swift 2 you could compare optionals directly (and nil was considered "less" than any non-nil value). Therefore in Swift 2 you could sort the array with

arr.sortInPlace { $0["name"] < $1["name"] }

However, the optional comparison operators have been removed in Swift 3 with the implementation of SE-0121 – Remove Optional Comparison Operators.

Therefore you have to unwrap $0["name"]. If you are 100% sure that every dictionary in the array has a "name" key then you can unwrap forcefully as Ahmad F suggested

arr.sort { $0["name"]! < $1["name"]! }

If that is not guaranteed then provide a default name, e.g. the empty string via the nil-coalescing operator ??:

arr.sort { ($0["name"] ?? "") < ($1["name"] ?? "") }

Example:

var arr = [["title":"Mrs","name":"Abc"], ["title":"Mr","name":"XYZ"], ["title": "Dr"]]
arr.sort { ($0["name"] ?? "") < ($1["name"] ?? "") }
print(arr)
// [["title": "Dr"], ["name": "Abc", "title": "Mrs"], ["name": "XYZ", "title": "Mr"]]

As one can see, the dictionary without a "name" key is ordered first. A simple way to sort entries without name last would be:

arr.sort { ($0["name"] ?? "\u{10FFFF}") < ($1["name"] ?? "\u{10FFFF}") }
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for clarification. In case of the key is not guaranteed to be "name", is there a way to let ["title": "Dr"] (or all dictionaries with no "name" key) to be at last of ordering?
@dfri: Is that the case? The sort is not stable.
@MartinR you're right, "" vs "" will naturally "suffer" from the non-stable sorting, my bad x)
@MartinR can you provide me your knowledge source? As I checked in the docs and there were none like that. It would be of much more help if I can learn them myself too.
4

Actually, I'm not pretty sure if arr.sort{$0.name < $1.name} worked in "older swift", however, it should be like:

var arr:Array<Dictionary<String, String>> = [["title":"Mr","name":"XYZ"], ["title":"Mrs","name":"Abc"]]

print(arr) // [["name": "XYZ", "title": "Mr"], ["name": "Abc", "title": "Mrs"]]

arr.sort {
    ($0["name"])! < ($1["name"])!
}

print(arr) // [["name": "Abc", "title": "Mrs"], ["name": "XYZ", "title": "Mr"]]

Hope it helped.

1 Comment

This was in older swift. Doesn't work in swift 3. Please have a look at expected syntax.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.