4

How is an array sorted by multiple criteria in Swift? For example, an array of dictionaries as shown:

items = [
    [
        "item":"itemA"
        "status":"0"
        "category":"B"
    ],[
        "item":"itemB"
        "status":"1"
        "category":"C"
    ],[
        "item":"itemC"
        "status":"0"
        "category":"A"
    ],[
        "item":"itemD"
        "status":"2"
        "category":"A"
    ]
]

This needs to be sorted as follows:

  1. category ASC
  2. status DESC

I have successfully sorted this array based on either condition 1 OR 2, but not both. Below is the code for that:

itemArray.sort({
        $0["category"] < $1["category"])
    })

How can this be expanded to include multiple sort criteria in a given order?

Michael Voccola
  • 1,827
  • 6
  • 20
  • 46

1 Answers1

12

You want a lexicographic comparison i.e. if the first fields are equal, compare the second fields, otherwise compare the first fields.

The dictionary complicates it a bit since you don’t want to fetch the data out twice and keys may be missing, but that’s actually fine since == and < can handle optional comparisons.

let result = items.sorted {
    switch ($0["category"],$1["category"]) {
    // if neither “category" is nil and contents are equal,
    case let (lhs,rhs) where lhs == rhs:
        // compare “status” (> because DESC order)
        return $0["status"] > $1["status"]
    // else just compare “category” using <
    case let (lhs, rhs):
        return lhs < rhs
    }
}

There’s actually a lexicographicCompare that you could use under some circumstances to do the comparison – but it won’t work in this case because a) optionals, while they can be compared with <, don’t conform to Comparable so you’d have to check for nils manually, and b) you want to sort the second entry in descending order.

Airspeed Velocity
  • 40,491
  • 8
  • 113
  • 118
  • Where is .Some(lhs) and .Some(RHS) generated / what do they represent? I would like to better understand this so I can add additional sort order criteria beyond the two in the example. – Michael Voccola Dec 22 '14 at 04:38
  • They were to check if the keys were missing - but then I realized it’s unnecessary since `==` can handle optionals of comparables. I’ve edited it to remove them. – Airspeed Velocity Dec 22 '14 at 04:41