'Order an array of objects by the value of their enums in swift
I have an array of CLBeacon objects which all have a property .proximity.
I want to order the array by this property which contains the CLProximity enum. So I want all objects to be in order IMMEDIATE, NEAR, FAR, UNKNOWN.
Is there a way to do this neatly without resorting to a bunch of if statements?
Solution 1:[1]
If you define a (computed read-only) property sortIndex of CLProximity
extension CLProximity {
var sortIndex : Int {
switch self {
case .Immediate:
return 0
case .Near:
return 1
case .Far:
return 2
case .Unknown:
return 3
}
}
}
then you can sort an array of beacons with
let sortedBeacons = sorted(beacons) { $0.proximity.sortIndex < $1.proximity.sortIndex }
If .Unknown is the only CLProximity value that needs
"special treatment" and all other possible values are in the desired
relative order then you can simplify the property definition to
extension CLProximity {
var sortIndex : Int {
return self == .Unknown ? Int.max : rawValue
}
}
Solution 2:[2]
You can use custom comparator and sort an array using that ,
You will "say" for all objects that has "unknown" proximity are "bigger" than others
var sortedArray = persons.sortedArrayUsingComparator {
(obj1, obj2) -> NSComparisonResult in
if obj1.proximity.rawValue == obj12.proximity.rawValue {
return NSComparisonResult.OrderedSame
} else if obj1.proximity == .UNKNOWN || obj1.proximity.rawValue > obj12.proximity.rawValue {
return NSComparisonResult.OrderedDescending
}
return NSComparisonResult.OrderedAscending
}
Solution 3:[3]
Based on what Julia wrote above I had cobbled this together:
self.beacons = beacons as! [CLBeacon]
var tempBeacons = zip(self.beacons, self.beacons.map({
(b: CLBeacon) -> Int in
if b.proximity == .Immediate {
return 0
} else if b.proximity == .Near {
return 1
} else if b.proximity == .Far {
return 2
} else if b.proximity == .Unknown {
return 3
}
return 0
}))
self.beacons = sorted(tempBeacons, {$0.1 < $1.1}).map({ $0.0 })
Thanks all!
Solution 4:[4]
Based on @Martin answer. You can also create Int enum and assign value to it and then sort it like below.
enum myEnum: Int {
case A = 0
case B = 1
case C = 2
case D = 3
}
let myData : [myEnum:[String]] = [.C:["3"],.D:["4"],.B:["2"],.A:["1"]]
print(myData.first?.key)
let newData = myData.sorted(by: { $0.key.rawValue < $1.key.rawValue })
print(newData.first?.key)
Hope this helps
Solution 5:[5]
Swift 5
Now you can just add Comparable to your enum and it respects the order
enum ContainerLevel: Comparable {
case empty
case almostEmpty
case halfFull
case almostFull
case full
}
//Are we running low?
let needMoreCoffee = coffeeMugLevel > .halfFull
print(needMoreCoffee) //true
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | ogres |
| Solution 3 | Alper |
| Solution 4 | Abdul Rehman |
| Solution 5 | devjme |
