简体   繁体   中英

swift - sort an array of objects by their optional boolean property without force unwrapping

I can sort this array of store objects by their 'flagship' boolean property, but how can I safely unwrap the 'flagship' property first?

let flagshipStores = self.stores.sort {
    $0.flagship! && !$1.flagship!
}
let flagshipStores = self.stores.sort {
    guard let flagship0 = $0.flagship, let flagship1 = $1.flagship else { return false }
    return flagship0 && !flagship1
}

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.

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.

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 )

 })

To filter nil values just use compactMap before sort

let flagshipStores = self.stores.compactMap { return $0.flagship }.sorted {
    $0 && !$1
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM