0

I want to determine if an enum is present in an enums list. Intuitively I would do this:

if myEnum == (.one || .two) { return true }
else { return false }

Of course it doesn't work.

I know that I could do:

if myEnum == .one || myEnum == .two { return true }
else { return false }

Or

if [EnumType.one, EnumType.two].contains(myEnum) { return true }
else { return false }

But I just want to be fancy today :)

I am thinking about using filter but it seems overkill.

Do you have an idea?

Thanks a lot.

Thierry

thierryb
  • 3,660
  • 4
  • 42
  • 58

5 Answers5

1

You can do

//: Playground - noun: a place where people can play

import Cocoa

enum MyEnum {
    case one
    case two
    case three
    case four
}

let list: [MyEnum] = [.one, .two, .three, .four]

if list.contains(.one) {
    // Contains
} else {
    // Doesn't Contain
}

If you have associated data you have to make your enum be Equatable for this to work though. For example:

//: Playground - noun: a place where people can play

import Cocoa

enum MyEnum: Equatable {
    case one
    case two
    case three
    case four
    case other(String)

    static func ==(lhs: MyEnum, rhs: MyEnum) -> Bool {
        switch (lhs, rhs) {
        case (.one, .one),
             (.two, .two),
             (.three, .three),
             (.four, .four):
            return true

        case (.other(let lhsString), .other(let rhsString)) where lhsString == rhsString:
            return true

        default:
            return false
        }
    }
}

let list: [MyEnum] = [.one, .two, .three, .four, .other("test")]

if list.contains(.one) {

} else {

}
1

I would do a switch on each one and then have a default for if you can't find either of those types.

switch myEnum {
    case .one:
        print("One is here baby")
    case .two:
        print("Two is here baby")
    default:
        print("Can't find the case??????")
    }
Andy Taylor
  • 102
  • 7
1

That's what OptionSet are for. It's technically a struct, but in usage, look very close to enum:

struct MyOptions : OptionSet {
    var rawValue: Int
    init(rawValue: Int) { self.rawValue = rawValue }

    static let one = MyOptions(rawValue: 1)
    static let two = MyOptions(rawValue: 2)
    static let three = MyOptions(rawValue: 4)
}


let option: MyOptions = [.one, .two]

if option.contains([.one, .two]) {
    print("Has one and two")
}

if !option.intersection([.one, .three]).isEmpty {
    print("Has one or three")
}
Code Different
  • 90,614
  • 16
  • 144
  • 163
0

I would use a switch as well and group the enum cases which are handled with common logic as follows:

enum MyEnum {
    case one
    case two
    case three
    case four
}

switch myEnum {
    case .one, .two:
        //deal with enum cases .one and .two
    default:
        //deal with all other cases
    }
}
J.beenie
  • 861
  • 10
  • 22
0

If you are trying to match arbitrary strings to various cases in your enum then you can do something like this (using Swift 3).

enum CompassPoint:String {
    case north
    case south
    case east
    case west

    static func has(key: String) -> Bool {
        for f in iterateEnum(CompassPoint.self) {
            if(f.rawValue == key) {
                return true;
            }
        }
        return false;
    }

    private static func iterateEnum<T: Hashable>(_: T.Type) -> AnyIterator<T> {
        var i = 0
        return AnyIterator {
            let next = withUnsafeBytes(of: &i) { $0.load(as: T.self)   }
            if next.hashValue != i { return nil }
            i += 1
            return next
        }
    }
}

CompassPoint.has(key: "south") // true
CompassPoint.has(key: "something") // false

Shoutout to @rintaro for his function for iterating over enums (found below). https://stackoverflow.com/a/28341290/5270038

Community
  • 1
  • 1