Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get index of enum with extension of String,

I have an Enum that looks like this:

enum Status: String {
    case online = "online"
    case offline = "offline"
    case na = "na"
}

I need the String value and I know how to get it, but my question is if it´s possible to get the index value too for each case in the enum.

0 for online, 1 for offline and 2 for na.

I will add more statues in the future.

like image 215
John S Avatar asked Jun 09 '17 07:06

John S


People also ask

How do you find the index of an enum?

Finding index of an enum constant The combination of valueOf() and ordinal() methods will be utilized in order to find the index of an enum constant. In the valueOf() method we have to mention the value whose index we want to find out.

Can you index into an enum?

Yes you can programmatically index an enum, text, or menu ring. An easy way to do this is to type cast the iteration terminal of a While or For Loop to the enum, text, or menu ring that you want to index. Note: The iteration terminal is an I32 and enum, text, and menu rings are of type U16 by default.

Does enum have index in Java?

each enum value knows its position (indexed from zero) which we can get by calling ordinal() method on it.

What are enum types?

An enum type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it. Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week.


2 Answers

-------- UPDATE -------

Since swift 4.2 you can do following:

enum Status: String, CaseIterable {

    case online
    case offline
    case na
}

extension CaseIterable where Self: Equatable {

    var index: Self.AllCases.Index? {
        return Self.allCases.index { self == $0 }
    }
}

or as I wrote earlier:

enum Status: Int {

    case online = 0
    case offline
    case na

    var index: Int {
        return rawValue
    }
    var value: String {
        return String(describing: self)
    }
}

-------- ORIGIN ANSWER -------

I'm using this extension:

protocol EnumIterable: RawRepresentable {

    static var allValues: [Self] { get }
    var index: Int? { get }
}

extension EnumIterable {

    static var count: Int {
        return allValues.count
    }
}

extension EnumIterable where Self.RawValue: Equatable {

    var next: Self? {
        if let index = Self.allValues.index(where: { rawValue == $0.rawValue }) {
            return Self.allValues[safe: index + 1]
        }
        return nil
    }

    var index: Int? {
        return Self.allValues.index { rawValue == $0.rawValue }
    }
}

But you would define allValues variable:

enum Status: String, EnumIterable {

    case online = "online"
    case offline = "offline"
    case na = "na"

    static var allValues: [Status] {
        return [
            .online,
            .offline,
            .na,
        ]
    }
}

Something similar was solved here (count of enumerations): How do I get the count of a Swift enum?

Next possibility is to define enum like this:

enum Status: Int {

    case online = 0
    case offline
    case na

    var index: Int {
        return rawValue
    }
    var value: String {
        return String(describing: self)
    }
}

print (Status.online.value) // online
print (Status.online.index) // 0

or

enum Status: Int {

    case online = 0
    case offline
    case na

    var index: Int {
        return rawValue
    }
    var value: String {
        switch self {
        case .online:
            return "online"
        case .offline:
            return "offline"
        case .na:
            return "na"
        }
    }
}

print (Status.online.value) // online
print (Status.online.index) // 0

Note: for defining string value, you can use CustomStringConvertible protocol.

Eg:

enum Status: Int, CustomStringConvertible {

    case online = 0
    case offline
    case na

    var index: Int {
        return rawValue
    }
    var description: String {
        switch self {
        case .online:
            return "online"
        case .offline:
            return "offline"
        case .na:
            return "na"
        }
    }
}
like image 148
JMI Avatar answered Oct 25 '22 01:10

JMI


As enum in Swift does not have index of its values (please read the post in Martin R's comment), you have to create your self some 'index' function or to map all values to an Array to have the index.

You can implement as in this post or another way to do:

enum Status: String {
    case online = "online"
    case offline = "offline"
    case na = "na"

    static func index(of aStatus: Status) -> Int {
        let elements = [Status.online, Status.offline, Status.na]

        return elements.index(of: aStatus)!
    }

    static func element(at index: Int) -> Status? {
        let elements = [Status.online, Status.offline, Status.na]

        if index >= 0 && index < elements.count {
            return elements[index]
        } else {
            return nil
        }
    }
}

let a = Status.na

//return 2
let index = Status.index(of: a)

//return Status.offline
let element2 = Status.element(at: 1)

//return nil
let element3 = Status.element(at: 3)
like image 33
Duyen-Hoa Avatar answered Oct 25 '22 03:10

Duyen-Hoa