web-dev-qa-db-ja.com

Swiftの列挙値をループする

Swiftで列挙値をループすることは可能ですか?または、代替手段は何ですか?

私はAppleのSwift言語ガイドを使って作業していますが、列挙型でこの例を見つけました。

//  EXPERIMENT
//
//  Add a method to Card that creates a full deck of cards, 
//  with one card of each combination of rank and suit.

struct Card {
    var rank: Rank
    var suit: Suit
    func simpleDescription() -> String {
        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
    }
}
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()

enum Suit {
    case Spades, Hearts, Diamonds, Clubs
    func simpleDescription() -> String {
        switch self {
        case .Spades:
            return "spades"
        case .Hearts:
            return "hearts"
        case .Diamonds:
            return "diamonds"
        case .Clubs:
            return "clubs"
        }
    }
}

enum Rank: Int {
    case Ace = 1
    case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
    case Jack, Queen, King
    func simpleDescription() -> String {
        switch self {
        case .Ace:
            return "ace"
        case .Jack:
            return "jack"
        case .Queen:
            return "queen"
        case .King:
            return "king"
        default:
            return String(self.toRaw())
        }
    }
}

抜粋:Apple Inc.“ Swiftプログラミング言語。” iBooks。 https://itun.es/us/jEUH0.l

私は次のことを試しましたが、ドキュメントでは、Swiftの列挙型にはCのような基礎となる整数値が割り当てられていないので、おそらく間違ったツリーを探しています。

この問題を解決するより良い方法はありますか?

func deck() -> Card[]{
    var deck: Card[]
    for s in Suit {
        for r in Rank {
            deck += Card(rank: r, suit: s)
        }
    }
    return deck
}

func deck2() -> Card[]{
    var deck: Card[]
    for var s: Suit = .Spades; s <= .Clubs; s++ {
        for var r: Rank = .Ace; r <= .King; r++ {
            deck += Card(rank: r, suit: s)
        }
    }
    return deck
}
30
glaslong

別の方法はありますか?承知しました。 better、それはあなたが決めることです:

_func generateDeck() -> Card[]
{
    let ranksPerSuit = 13
    var deck = Card[]()

    for index in 0..52
    {
        let suit = Suit.fromRaw(index / ranksPerSuit)
        let rank = Rank.fromRaw(index % ranksPerSuit + 1)

        let card = Card(rank: rank!, suit: suit!)
        deck.append(card)
    }

    return deck
}

let deck = generateDeck()

for card : Card in deck { println("\(card.description)") }
_

これを使用するには、RankSuitの両方の列挙型が、その型定義にIntを使用していることを確認する必要があります(例:_enum Rank : Int_)。

_Rank.Ace_は_1_と等しく、最初のSuitケースは_0_と等しくなければなりません。

既存のコードと同様にループしたい場合は、Rank.King.toRaw()などを使用できるように、列挙型をInt型にする必要があります。

Appleのドキュメントでは、列挙型は「単純な整数値」に制限されているわけではありませんが、希望する場合は確実に指定できます。

[〜#〜] update [〜#〜]

@ jay-imermanによるコメントからのアイデアで、Swift 5に適用可能

_extension Rank: CaseIterable {}
extension Suit: CaseIterable {}

func generateDeck() -> [Card] {
    var deck = [Card]();

    Rank.allCases.forEach {
        let rank = $0

        Suit.allCases.forEach {
            let suit = $0

            deck.append(Card(rank: rank, suit: suit))
        }
    }

    return deck;
}
_
18
Erik