I can sort this array of store objects by their \'flagship\' boolean property, but how can I safely unwrap the \'flagship\' property first?
le
To filter nil
values just use compactMap
before sort
let flagshipStores = self.stores.compactMap { return $0.flagship }.sorted {
$0 && !$1
}
How about:
$0.flagship == true && $1.flagship != true
The left side will succeed if the value is not nil and is true, the right side will succeed if the value is either nil or false.
As mr.Fixit pointed out on a comment, the accepted answer doesn't fully work because it doesn't take care of nils. Here is the correct answer with an extra string sample.
SWIFT 4
for a boolean sorting
let flagshipStores = self.stores.sorted(by: {
guard let flagship0 = $0.flagship, let flagship1 = $1.flagship else {
if $0.flagship == nil && $1.flagship == nil || $0.flagship != nil && $1.flagship == nil{
return true
}
else {
return false
}
}
return ($0.flagship == $1.flagship || $0.flagship == true && $1.flagship == false ? true : false)
})
for strings comparison sorting
let stores = self.stores.sorted(by: {
guard let store0 = $0.store, let store1 = $1.store else {
if $0.store == nil && $1.store == nil || $0.store != nil && $1.store == nil{
return true
}
else {
return false
}
}
return ( ($0.store)?.localizedStandardCompare($1.store!) == ComparisonResult.orderedAscending )
})
Here's another approach.
You can use flatMap
which will remove nil
objects and unwrap those that are present. Then, the force unwrap will be safe to sort:
let flagshipStores = stores.flatMap({ return $0.flagship ? $0 : nil }).sort {
$0.flagship! && !$1.flagship!
}
This will remove stores with a nil
flagship from the array.
One more approach: turn the Bool?
into an Int
, then compare the Int
s. You get to specify how a nil
value compares to non-nil
values.
For instance, this sorts nil
values before both false
and true
:
stores.sort { Int($0.flagship ?? -1) < Int($1.flagship ?? -1) }
This sorts nil
values after both false
and true
:
stores.sort { Int($0.flagship ?? 2) < Int($1.flagship ?? 2) }
You can use the same pattern to make nil
compare the same as true
or the same as false
. It's up to you.
let flagshipStores = self.stores.sort {
guard let flagship0 = $0.flagship, let flagship1 = $1.flagship else { return false }
return flagship0 && !flagship1
}