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:

2voto

Alaeddine Punkte 5662

Beim Umgang mit Swift 2.0 hier ist mein Vorschlag:

Ich habe den Raw-Typ zu Suit enum hinzugefügt.

enum Suit: Int {

dann:

struct Card {
    var rank: Rank
    var suit: Suit

    func fullDeck()-> [Card] {

        var deck = [Card]()

        for i in Rank.Ace.rawValue...Rank.King.rawValue {

            for j in Suit.Spades.rawValue...Suit.Clubs.rawValue {

                deck.append(Card(rank:Rank(rawValue: i)! , suit: Suit(rawValue: j)!))
            }
        }

        return deck
    }
}

2voto

gleb vodovozov Punkte 297

Ich habe dies mit einer berechneten Eigenschaft gemacht, die das Array aller Werte zurückgibt (danke an diesen Beitrag http://natecook.com/blog/2014/10/loopy-random-enum-ideas/). Allerdings verwendet es auch int raw-Werte, aber ich muss nicht alle Elemente der Aufzählung in separater Eigenschaft wiederholen.

UPDATE Xcode 6.1 hat ein wenig die Art geändert, wie man ein Enum-Mitglied mithilfe von rawValue bekommt, also habe ich die Liste korrigiert. Auch einen kleinen Fehler mit dem falschen ersten rawValue korrigiert.

enum ValidSuits: Int {
    case Clubs = 0, Spades, Hearts, Diamonds
    func description() -> String {
        switch self {
        case .Clubs:
            return ""
        case .Spades:
            return ""
        case .Diamonds:
            return ""
        case .Hearts:
            return ""
        }
    }

    static var allSuits: [ValidSuits] {
        return Array(
            SequenceOf {
                () -> GeneratorOf in
                var i=0
                return GeneratorOf {
                    return ValidSuits(rawValue: i++)
                }
            }
        )
    }
}

2voto

Roger Worden Punkte 21

Hier ist mein vorgeschlagener Ansatz. Es ist nicht vollständig zufriedenstellend (ich bin ganz neu in Swift und OOP!), aber vielleicht kann es jemand verfeinern. Die Idee ist, dass jede Aufzählung ihre eigenen Bereichsinformationen als .first und .last Eigenschaften bereitstellt. Es fügt nur zwei Codezeilen zu jeder Aufzählung hinzu: immer noch etwas hart kodiert, aber zumindest dupliziert es nicht den gesamten Satz. Es erfordert jedoch, dass die Suit Aufzählung wie die Rank Aufzählung ein Int ist, anstatt ungetypt.

Anstatt die gesamte Lösung zu wiederholen, hier ist der Code, den ich zur . Aufzählung hinzugefügt habe, irgendwo nach den case-Anweisungen (die Suit Aufzählung ist ähnlich):

var first: Int { return Ace.toRaw() }
var last: Int { return King.toRaw() }

und die Schleife, die ich verwendet habe, um das Deck als Array von String aufzubauen. (Die Problemdefinition gab nicht an, wie das Deck strukturiert sein sollte.)

func createDeck() -> [String] {
    var deck: [String] = []
    var card: String
    for r in Rank.Ace.first...Rank.Ace.last {
        for s in Suit.Hearts.first...Suit.Hearts.last {
            card = Rank.simpleDescription( Rank.fromRaw(r)!)() + " von " + Suit.simpleDescription( Suit.fromRaw(s)!)()
           deck.append( card)
       }
    }
    return deck
}

Es ist unbefriedigend, weil die Eigenschaften mit einem Element anstatt mit der Aufzählung verknüpft sind. Aber es trägt zur Klarheit der 'for'-Schleifen bei. Ich hätte gerne, dass es Rank.first statt Rank.Ace.first sagt. Es funktioniert (mit jedem Element), aber es ist hässlich. Kann jemand zeigen, wie man das auf die Ebene der Aufzählung anheben kann?

Und um es zum Laufen zu bringen, habe ich die createDeck Methode aus der Card-Struktur gehoben. Ich konnte nicht herausfinden, wie man ein [String] Array aus dieser Struktur zurückbekommt, und das scheint sowieso kein guter Ort für eine solche Methode zu sein.

2voto

KenH Punkte 47

Dies scheint wie ein Hack, aber wenn Sie Rohwerte verwenden, können Sie so etwas tun

enum Suit: Int {  
    case Spades = 0, Hearts, Diamonds, Clubs  
 ...  
}  

var suitIndex = 0  
while var suit = Suit.fromRaw(suitIndex++) {  
   ...  
}

2voto

Enums haben toRaw() und fromRaw() Methoden. Wenn also dein Rohwert ein Int ist, kannst du von der ersten bis zur letzten enum iterieren:

enum Suit: Int {
    case Spades = 1
    case Hearts, Diamonds, Clubs
    func simpleDescription() -> String {
        switch self {
        case .Spades:
            return "Pik"
        case .Hearts:
            return "Herz"
        case .Diamonds:
            return "Karo"
        case .Clubs:
            return "Kreuz"
        }
    }
}

for i in Suit.Spades.toRaw()...Suit.Clubs.toRaw() {
    if let covertedSuit = Suit.fromRaw(i) {
        let description = covertedSuit.simpleDescription()
    }
}

Ein Problem, auf das man achten muss, ist, dass man optionalen Werten testen muss, bevor man die simpleDescription Methode ausführt. Deshalb setzen wir zuerst convertedSuit auf unseren Wert und setzen dann eine Konstante auf convertedSuit.simpleDescription()

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