Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sort objects by its enum value?

Tags:

swift

I've got Workout class with Difficulty property

enum Difficulty: String {
  case easy = "easy"
  case moderate = "moderate"
  case hard = "hard"
}

class Workout {
  var name: String?
  var difficulty: Difficulty?
  .
  .
  .
}

I'd like to sort an array of workouts by the difficulty property. I know I can achieve that by assigning enum's raw value to Int value and compare these values as follows:

data.sort { $0.workout.difficulty!.rawValue < $1.workout.difficulty!.rawValue }

But I really want this enum to store string, since it's convenient to assign it to label text down the line without ugly switch-case hacks, and be comparable in some way.

How to achieve that?

like image 352
theDC Avatar asked Oct 21 '17 14:10

theDC


People also ask

Are enum values sorted?

ENUM values are sorted based on their index numbers, which depend on the order in which the enumeration members were listed in the column specification.

How do you sort a list of objects based on an attribute of the objects in Java?

In the main() method, we've created an array list of custom objects list, initialized with 5 objects. For sorting the list with the given property, we use the list's sort() method. The sort() method takes the list to be sorted (final sorted list is also the same) and a comparator.

What is the order of values in an enum?

These values are public static final , ie (Constant objects of that specific Enum Type), and its Order is very Important for mapping the variables to these Objects. values() is a static method of Enum , which always returns the values in same order.

How can we sort a list of objects?

sort() method to sort a list of objects using some examples. By default, the sort() method sorts a given list into ascending order (or natural order). We can use Collections. reverseOrder() method, which returns a Comparator, for reverse sorting.


Video Answer


2 Answers

Implement the Comparable protocol on your enum. It gives you a static func < (lhs: Difficulty, rhs: Difficulty) -> Bool method where you define the sort.

Here is a full sample using a property to simplify the ordering

enum Difficulty: String, Comparable {
    case easy = "easy"
    case moderate = "moderate"
    case hard(String) = "hard"

    private var sortOrder: Int {
        switch self {
            case .easy:
                return 0
            case .moderate:
                return 1
            case .hard(_):
                return 2
        }
    }

     static func ==(lhs: Difficulty, rhs: Difficulty) -> Bool {
        return lhs.sortOrder == rhs.sortOrder
    }

    static func <(lhs: Difficulty, rhs: Difficulty) -> Bool {
       return lhs.sortOrder < rhs.sortOrder
    }
}

Making it possible to use

data.sort { $0.workout.difficulty! < $1.workout.difficulty! }
like image 171
Igor Kulman Avatar answered Oct 23 '22 16:10

Igor Kulman


edit/update: Swift 5.1 or later

You can change your enumeration RawValue type to integer and use its rawValue to sort your Workouts. Btw you should use a structure instead of a class and similar to what was suggested by Igor you could make your struct comparable instead of the enumeration:

struct Workout {
    let name: String
    let difficulty: Difficulty
}

extension Workout {
    enum Difficulty: Int { case easy, moderate, hard }
}


extension Workout: Comparable {
    static func <(lhs: Workout, rhs: Workout) -> Bool { lhs.difficulty.rawValue < rhs.difficulty.rawValue }
}

let wk1 = Workout(name: "night", difficulty: .hard)
let wk2 = Workout(name: "morning", difficulty: .easy)
let wk3 = Workout(name: "afternoon", difficulty: .moderate)

let workouts = [wk1, wk2, wk3]  // [{name "night", hard}, {name "morning", easy}, {name "afternoon", moderate}]

let sorted = workouts.sorted()  // [{name "morning", easy}, {name "afternoon", moderate}, {name "night", hard}]
like image 45
Leo Dabus Avatar answered Oct 23 '22 17:10

Leo Dabus