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

前端 未结 6 554
旧巷少年郎
旧巷少年郎 2021-01-02 00:02

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

le         


        
相关标签:
6条回答
  • 2021-01-02 00:39

    To filter nil values just use compactMap before sort

    let flagshipStores = self.stores.compactMap { return $0.flagship }.sorted {
        $0 && !$1
    }
    
    0 讨论(0)
  • 2021-01-02 00:45

    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.

    0 讨论(0)
  • 2021-01-02 00:53

    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 )
    
     })
    
    0 讨论(0)
  • 2021-01-02 00:55

    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.

    0 讨论(0)
  • 2021-01-02 01:01

    One more approach: turn the Bool? into an Int, then compare the Ints. 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.

    0 讨论(0)
  • 2021-01-02 01:05
    let flagshipStores = self.stores.sort {
        guard let flagship0 = $0.flagship, let flagship1 = $1.flagship else { return false }
        return flagship0 && !flagship1
    }
    
    0 讨论(0)
提交回复
热议问题