Choosing a random value from an enumeration sub-section

Given the Swift enumeration as such:

enum PerformerPosition: Int {

    case String_Violin1
    case String_Violin2
    case String_Viola
    case String_Cello
    case String_CB

    case Wind_Oboe
    case Wind_Clarinet
    case Wind_Flute
    ...

}

(For the needs of the project, I may not have a nested enumeration.) I would like to randomly select an enumeration value with only a prefix String_.

The only way I know so far is to make a random enumeration value from all available cases, as such:

private static let _count: PerformerPosition.RawValue = {
    // find the maximum enum value
    var maxValue: Int = 0
    while let _ = PerformerPosition(rawValue: maxValue) { 
        maxValue += 1
    }
    return maxValue
}()

static func randomPerformer() -> PerformerPosition {
    // pick and return a new value
    let rand = arc4random_uniform(UInt32(count))
    return PlayerPosition(rawValue: Int(rand))!
}

How can I do this, so I can choose a random value based on the prefix String_ without , to resort to hard coding the upper value (for example, a new String_prefix position can be added)? Thanks

+6
source share
3 answers

, - , ​​ . ?

, . :

protocol EnumCollection : Hashable {}
extension EnumCollection {
    static func cases() -> AnySequence<Self> {
        typealias S = Self
        return AnySequence { () -> AnyIterator<S> in
            var raw = 0
            return AnyIterator {
                let current : Self = withUnsafePointer(to: &raw) { $0.withMemoryRebound(to: S.self, capacity: 1) { $0.pointee } }
                guard current.hashValue == raw else { return nil }
                raw += 1
                return current
            }
        }
    }
}

, cases, , :

let startingWithString = Array(PerformerPosition.cases().filter { "\($0)".hasPrefix("String_") })
let rand = arc4random_uniform(UInt32(startingWithString.count))
let randomPosition = startingWithString[Int(rand)]
+2

, , , :

enum PerformerPosition: Int {

    case String_Violin1
    case String_Violin2
    case String_Viola
    case String_Cello
    case String_CB

    case Wind_Oboe
    case Wind_Clarinet
    case Wind_Flute

    static let strings: [PerformerPosition] = [
        .String_Violin1, .String_Violin2, .String_Viola, .String_Cello, .String_CB
    ]

    static let winds: [PerformerPosition] = [
        .Wind_Oboe, .Wind_Clarinet, .String_Viola, .Wind_Flute
    ]
}

, :

  • String_ Wind_. .violin1, .oboe ..

  • :

    let isString = PerformerPosition.strings.contains(.violin1)
    
+1

PlayGround:

func randomPerformer() -> PerformerPosition {
    // pick and return a new value
    let rand = arc4random_uniform(_count)
    let string = String(describing:PerformerPosition(rawValue: rand))
    if(string.contains("String_")){
            return PerformerPosition(rawValue: rand)!
    }else{
            return randomPerformer()
    }
}
0

Source: https://habr.com/ru/post/1016211/


All Articles