user14785646
user14785646

Reputation:

Sort array in swiftui by multiple conditions

how it is possible to sort an array by multiple conditions.

struct UserInformationModel: Identifiable, Hashable {
    
    let id = UUID()
    var isVip: Bool
    let userIsMale: Bool
    let userName: String
    let age: Int
    let userCountry: String
    let countryIsoCode: String
    let uid: String
    
}

And the view model contain the code:

class GetUserInformationViewModel: ObservableObject {
    
    @Published var allUsers = [UserInformationModel]()

 fun sortmyarray(){
   
  self.allUsers = self.allUsers.sorted(by: {$0.isVip && !$1.isVip})

}

how its possible to sort first the vip users, and then sort by age and then country?

Upvotes: 1

Views: 960

Answers (2)

Joakim Danielson
Joakim Danielson

Reputation: 51892

Here is a simple way to sort on multiple properties (I have assumed a sort order here for each property since it isn't mentioned in the question)

let sorted = users.sorted {
    if $0.isVip == $1.isVip {
        if $0.age == $1.age {
            return $0.userCountry < $1.userCountry
        } else {
            return $0.age < $1.age
        }
    }
    return $0.isVip && !$1.isVip
}

If the above is the natural sort order for the type then you could let the type implement Comparable and implement the < func

struct UserInformationModel: Identifiable, Hashable, Comparable {
    //properties removed for brevity 

    static func < (lhs: UserInformationModel, rhs: UserInformationModel) -> Bool {
        if lhs.isVip == rhs.isVip {
            if lhs.age == rhs.age {
                return lhs.userCountry < rhs.userCountry
            } else {
                return lhs.age < rhs.age
            }
        }
        return lhs.isVip && !rhs.isVip
    }
}

and then the sorting would be

let sorted = users.sorted()

Upvotes: 4

user652038
user652038

Reputation:

Use tuples.

allUsers.sorted {
  ($1.isVip.comparable, $0.age, $0.userCountry)
  <
  ($0.isVip.comparable, $1.age, $1.userCountry)
}
public extension Bool {
  /// A way to compare `Bool`s.
  ///
  /// Note: `false` is "less than" `true`.
  enum Comparable: CaseIterable, Swift.Comparable {
    case `false`, `true`
  }

  /// Make a `Bool` `Comparable`, with `false` being "less than" `true`.
  var comparable: Comparable { .init(booleanLiteral: self) }
}

extension Bool.Comparable: ExpressibleByBooleanLiteral {
  public init(booleanLiteral value: Bool) {
    self = value ? .true : .false
  }
}

Upvotes: 1

Related Questions