607 Stimmen

Wie nummeriert man einen Aufzählungstyp mit String-Typ?

enum Suit: String {
    case spades = ""
    case hearts = ""
    case diamonds = ""
    case clubs = ""
}

Zum Beispiel, wie kann ich so etwas machen:

for suit in Suit {
    // Bearbeite etwas mit dem Anzug
    print(suit.rawValue)
}

Ergebnisbeispiel:

3voto

Hans-Peter Punkte 31

Das Experiment war: EXPERIMENT

Fügen Sie eine Methode zu Card hinzu, die ein volles Kartenspiel erstellt, mit einer Karte jeder Kombination von Rang und Farbe.

Also ohne den gegebenen Code zu ändern oder zu erweitern, außer der Methode hinzuzufügen (und ohne Dinge zu verwenden, die noch nicht gelehrt wurden), habe ich diese Lösung entwickelt:

struct Card {
    var rank: Rank
    var suit: Suit

    func simpleDescription() -> String {
        return "Der \(rank.simpleDescription()) von \(suit.simpleDescription())"
    }

    func createDeck() -> [Card] {
        var deck: [Card] = []
        for rank in Rank.Ace.rawValue...Rank.King.rawValue {
            for suit in Suit.Spades.rawValue...Suit.Clubs.rawValue {
                let card = Card(rank: Rank(rawValue: rank)!, suit: Suit(rawValue: suit)!)
                //println(card.simpleDescription())
                deck += [card]
            }
        }
        return deck
    }
}
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()
let deck = threeOfSpades.createDeck()

3voto

MkSMC Punkte 101

Hier ist eine Methode, die ich verwende, um sowohl ein enum zu durchlaufen als auch mehrere Werttypen aus einem enum zu erhalten

enum IterateEnum: Int {
    case Zero
    case One
    case Two
    case Three
    case Four
    case Five
    case Six
    case Seven

    //Ein Tuple ermöglicht es, mehrere Werte aus dem Enum-Fall abzuleiten, und
    //da es ein Switch ohne Default verwendet, wird ein Compilerfehler zurückgegeben, wenn ein neuer Fall hinzugefügt wird,
    //aber kein Wert-Tupel festgelegt ist
    var value: (french: String, spanish: String, japanese: String) {
        switch self {
        case .Zero: return (french: "zéro", spanish: "cero", japanese: "nuru")
        case .One: return (french: "un", spanish: "uno", japanese: "ichi")
        case .Two: return (french: "deux", spanish: "dos", japanese: "ni")
        case .Three: return (french: "trois", spanish: "tres", japanese: "san")
        case .Four: return (french: "quatre", spanish: "cuatro", japanese: "shi")
        case .Five: return (french: "cinq", spanish: "cinco", japanese: "go")
        case .Six: return (french: "six", spanish: "seis", japanese: "roku")
        case .Seven: return (french: "sept", spanish: "siete", japanese: "shichi")
        }
    }

    //Wird verwendet, um das Enum zu durchlaufen oder anderweitig auf den Enum-Fall nach Indexreihenfolge zuzugreifen.
    //Durchlauf durch Schleife, bis nil zurückgegeben wird
    static func item(index: Int) -> IterateEnum? {
        return IterateEnum.init(rawValue: index)
    }

    static func numberFromSpanish(number: String) -> IterateEnum? {
        return findItem { $0.value.spanish == number }
    }

    //Block verwenden, um den Wert der Eigenschaft zu testen, um den Enum-Fall abzurufen        
    static func findItem(predicate: ((_: IterateEnum) -> Bool)) -> IterateEnum? {

        var enumIndex: Int = -1
        var enumCase: IterateEnum?

        //Bis zum Nullpunkt durchlaufen
        repeat {
            enumIndex += 1
            enumCase = IterateEnum.item(index: enumIndex)

            if let eCase = enumCase {

                if predicate(eCase) {
                    return eCase
                }
            }
        } while enumCase != nil
        return nil
    }
}

var enumIndex: Int = -1
var enumCase: IterateEnum?

// Durchlauf durch Schleife, bis nil zurückgegeben wird
repeat {
    enumIndex += 1
    enumCase = IterateEnum.item(index: enumIndex)
    if let eCase = enumCase {
        print("Die Zahl \(eCase) auf Französisch: \(eCase.value.french), spanisch: \(eCase.value.spanish), japanisch: \(eCase.value.japanese)")
    }
} while enumCase != nil

print("Insgesamt \(enumIndex) Fälle")

let number = IterateEnum.numberFromSpanish(number: "siete")

print("siete auf Japanisch: \((number?.value.japanese ?? "Unbekannt"))")

Dies ist die Ausgabe:

Die Zahl Zero auf Französisch: zéro, spanisch: cero, japanisch: nuru
Die Zahl One auf Französisch: un, spanisch: uno, japanisch: ichi
Die Zahl Two auf Französisch: deux, spanisch: dos, japanisch: ni
Die Zahl Three auf Französisch: trois, spanisch: tres, japanisch: san
Die Zahl Four auf Französisch: quatre, spanisch: cuatro, japanisch: shi
Die Zahl Five auf Französisch: cinq, spanisch: cinco, japanisch: go
Die Zahl Six auf Französisch: six, spanisch: seis, japanisch: roku
Die Zahl Seven auf Französisch: sept, spanisch: siete, japanisch: shichi

Insgesamt 8 Fälle

siete auf Japanisch: shichi


UPDATE

Ich habe kürzlich ein Protokoll erstellt, um die Aufzählung zu behandeln. Das Protokoll erfordert ein Enum mit einem Int-Rohwert:

protocol EnumIteration {

    //Wird verwendet, um die Aufzählung zu durchlaufen oder anderweitig auf den Enum-Fall nach Indexreihenfolge zuzugreifen. Durchlauf durch Schleife, bis nil zurückgegeben wird

    static func item(index:Int) -> Self?
    static func iterate(item:((index:Int, enumCase:Self)->()), completion:(()->())?)
    static func findItem(predicate:((enumCase:Self)->Bool)) -> Self?
    static func count() -> Int
}

extension EnumIteration where Self: RawRepresentable, Self.RawValue == Int {

    //Wird verwendet, um die Aufzählung zu durchlaufen oder anderweitig auf den Enum-Fall nach Indexreihenfolge zuzugreifen. Durchlauf durch Schleife, bis nil zurückgegeben wird
    static func item(index:Int) -> Self? {
        return Self.init(rawValue: index)
    }

    static func iterate(item:((index:Int, enumCase:Self)->()), completion:(()->())?) {

        var enumIndex:Int = -1
        var enumCase:Self?

        //Durchlauf bis nil zurückgegeben wird
        repeat {
            enumIndex += 1
            enumCase = Self.item(enumIndex)

            if let eCase = enumCase {
                item(index: enumIndex, enumCase: eCase)
            }
        } while enumCase != nil
        completion?()
    }

    static func findItem(predicate:((enumCase:Self)->Bool)) -> Self? {

        var enumIndex:Int = -1
        var enumCase:Self?

        //Durchlauf, bis nil zurückgegeben wird
        repeat {
            enumIndex += 1
            enumCase = Self.item(enumIndex)

            if let eCase = enumCase {

                if predicate(enumCase:eCase) {
                    return eCase
                }
            }
        } while enumCase != nil
        return nil
    }

    static func count() -> Int {
        var enumIndex:Int = -1
        var enumCase:Self?

        //Durchlauf, bis nil zurückgegeben wird
        repeat {
            enumIndex += 1
            enumCase = Self.item(enumIndex)
        } while enumCase != nil

        //letzter enumIndex (wenn enumCase == nil) entspricht der Anzahl der Enumerationen
        return enumIndex
    }
}

2voto

Abbey Jackson Punkte 885

Dies ist ein ziemlich alter Beitrag, von Swift 2.0. Es gibt jetzt einige bessere Lösungen hier, die neuere Funktionen von Swift 3.0 verwenden: Durch Iteration durch ein Enum in Swift 3.0

Und zu dieser Frage gibt es eine Lösung, die eine neue Funktion von (der zum Zeitpunkt dieses Bearbeitungsschreibens noch nicht veröffentlichten) Swift 4.2 verwendet: Wie erhalte ich die Anzahl eines Swift-Enums?


Es gibt viele gute Lösungen in diesem Thread und in anderen, jedoch sind einige von ihnen sehr kompliziert. Ich versuche, so einfach wie möglich zu machen. Hier ist eine Lösung, die möglicherweise für verschiedene Bedürfnisse funktioniert oder auch nicht, aber ich denke, sie funktioniert in den meisten Fällen gut:

enum Number: String {
    case One
    case Two
    case Three
    case Four
    case EndIndex

    func nextCase () -> Number
    {
        switch self {
        case .One:
            return .Two
        case .Two:
            return .Three
        case .Three:
            return .Four
        case .Four:
            return .EndIndex

        /* 
        Füge alle zusätzlichen Fälle darüber hinzu
        */
        case .EndIndex:
            return .EndIndex
        }
    }

    static var allValues: [String] {
        var array: [String] = Array()
        var number = Number.One

        while number != Number.EndIndex {
            array.append(number.rawValue)
            number = number.nextCase()
        }
        return array
    }
}

Zur Iteration:

for item in Number.allValues {
    print("Zahl ist: \(item)")
}

2voto

Peymankh Punkte 1894

Wie bei der Antwort von @Kametrixom hier glaube ich, dass es besser wäre, ein Array zurückzugeben als AnySequence, da Sie dann Zugriff auf alle guten Dinge von Array haben, wie z.B. count, usw.

Hier ist die Neuformulierung:

public protocol EnumCollection : Hashable {}
extension EnumCollection {
    public static func allValues() -> [Self] {
        typealias S = Self
        let retVal = AnySequence { () -> AnyGenerator in
            var raw = 0
            return AnyGenerator {
                let current : Self = withUnsafePointer(&raw) { UnsafePointer($0).memory }
                guard current.hashValue == raw else { return nil }
                raw += 1
                return current
            }
        }

        return [S](retVal)
    }
}

2voto

Miguel Gallego Punkte 377

Eine weitere Lösung:

enum Suit: String {
    case spades = ""
    case hearts = ""
    case diamonds = ""
    case clubs = ""

    static var count: Int {
        return 4   
    }

    init(index: Int) {
        switch index {
            case 0: self = .spades
            case 1: self = .hearts
            case 2: self = .diamonds
            default: self = .clubs
        }
    }
}

for i in 0..

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X