天天看點

如何枚舉String類型的枚舉?

本文翻譯自:How to enumerate an enum with String type?

enum Suit: String {
    case spades = "♠"
    case hearts = "♥"
    case diamonds = "♦"
    case clubs = "♣"
}
           

For example, how can I do something like:

例如,我該怎麼做:
for suit in Suit {
    // do something with suit
    print(suit.rawValue)
}
           

Resulting example:

結果示例:
♠
♥
♦
♣
           

#1樓

參考:https://stackoom.com/question/1cjR7/如何枚舉String類型的枚舉

#2樓

Enums have

toRaw()

and

fromRaw()

methods.

枚舉具有

toRaw()

fromRaw()

方法。

So if your raw value is an

Int

, you can iterate from the first to last

enum

:

是以,如果原始值為

Int

,則可以從第一個

enum

到最後一個

enum

進行疊代:
enum Suit: Int {
    case Spades = 1
    case Hearts, Diamonds, Clubs
    func simpleDescription() -> String {
        switch self {
        case .Spades:
            return "spades"
        case .Hearts:
            return "hearts"
        case .Diamonds:
            return "diamonds"
        case .Clubs:
            return "clubs"
        }
    }
}

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

One gotcha is that you need to test for optional values before running the

simpleDescription

method, so we set

convertedSuit

to our value first and then set a constant to

convertedSuit.simpleDescription()

有一個問題是,你需要測試可選值運作之前

simpleDescription

方法,是以我們設定

convertedSuit

首先我們的價值,然後一個常數設定為

convertedSuit.simpleDescription()

#3樓

In principle it is possible to do it this way assuming that you don't use raw values assignment for enum's cases:

原則上,假設您在枚舉的情況下不使用原始值配置設定,則可以這樣做:
enum RankEnum: Int {
  case Ace
  case One
  case Two
}

class RankEnumGenerator: Generator {
    var i = 0
    typealias Element = RankEnum
    func next() -> Element? {
        let r = RankEnum.fromRaw(i)
        i += 1
        return r
    }
}

extension RankEnum {
    static func enumerate() -> SequenceOf<RankEnum> {
        return SequenceOf<RankEnum>({ RankEnumGenerator() })
    }
}

for r in RankEnum.enumerate() {
    println("\(r.toRaw())")
}
           

#4樓

This seems like a hack but if you use raw values you can do something like this

這似乎是一種hack,但是如果您使用原始值,則可以執行以下操作
enum Suit: Int {  
    case Spades = 0, Hearts, Diamonds, Clubs  
 ...  
}  

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

#5樓

I have used the below method, the assumption is that I know which is the last value in the Rank enum and all the ranks have incremental values after Ace

我使用以下方法,假設我知道哪個是Rank枚舉中的最後一個值,并且所有等級在Ace之後都具有增量值

I prefer this way as it is clean and small, easy to understand

我喜歡這種方式,因為它既幹淨又小巧,易于了解
func cardDeck() -> Card[] {
    var cards: Card[] = []
    let minRank = Rank.Ace.toRaw()
    let maxRank = Rank.King.toRaw()

    for rank in minRank...maxRank {
        if var convertedRank: Rank = Rank.fromRaw(rank) {
            cards.append(Card(rank: convertedRank, suite: Suite.Clubs))
            cards.append(Card(rank: convertedRank, suite: Suite.Diamonds))
            cards.append(Card(rank: convertedRank, suite: Suite.Hearts))
            cards.append(Card(rank: convertedRank, suite: Suite.Spades))
        }
    }

    return cards
}
           

#6樓

There is a clever way, and frustrating as it is it illustrates the difference between the two different kinds of enums.

有一個聰明的方法,令人沮喪,因為它說明了兩種不同的枚舉之間的差別。

Try this:

嘗試這個:
func makeDeck() -> Card[] {
      var deck: Card[] = []
      var suits: Suit[] = [.Hearts, .Diamonds, .Clubs, .Spades]
      for i in 1...13 {
        for suit in suits {
          deck += Card(rank: Rank.fromRaw(i)!, suit: suit)
        }
      }
      return deck
    }
           

The deal is that an enum backed by numbers (raw values) is implicitly explicitly ordered, whereas an enum that isn't backed by numbers is explicitly implicitly unordered.

問題在于,由數字(原始值)支援的枚舉是隐式顯式排序的,而沒有數字支援的枚舉是隐式無序的。

Eg when we give the enum values numbers, the language is cunning enough to figure out what order the numbers are in. If on the other hand we don't give it any ordering, when we try to iterate over the values the language throws its hands up in the air and goes "yes, but which one do you want to go first???"

例如,當我們給枚舉值一個數字時,該語言就足夠狡猾地找出數字的順序。另一方面,如果我們不給它任何順序,則當我們嘗試周遊這些值時,該語言将抛出舉手示意, “是的,但是你想先走哪一個???”

Other languages which can do this (iterating over unordered enums) might be the same languages where everything is 'under the hood' actually a map or dictionary, and you can iterate over the keys of a map, whether there's any logical ordering or not.

可以執行此操作的其他語言(周遊無序枚舉)可能是相同的語言,實際上所有内容都在“底層”,實際上是地圖或字典,并且您可以周遊地圖的鍵,無論是否存在邏輯順序。

So the trick is to provide it with something that is explicitly ordered, in this case instances of the suits in an array in the order we want.

是以,訣竅是為它提供明确排序的内容,在這種情況下,将以我們想要的順序排列數組中的衣服執行個體。

As soon as you give it that, Swift is like "well why didn't you say so in the first place?"

一旦您給出它,Swift就好像“那您為什麼不首先說出來?”

The other shorthand trick is to use the forcing operator on the fromRaw function.

另一個速記技巧是在fromRaw函數上使用強制運算符。

This illustrates another 'gotcha' about enums, that the range of possible values to pass in is often larger than the range of enums.

這說明了有關枚舉的另一個“陷阱”,即傳入的可能值的範圍通常大于枚舉的範圍。

For instance if we said Rank.fromRaw(60) there wouldn't be a value returned, so we're using the optional feature of the language, and where we start using optionals, forcing will soon follow.

例如,如果我們說Rank.fromRaw(60)不會傳回任何值,那麼我們将使用該語言的可選功能,并且在我們開始使用可選功能的地方,強制将很快出現。

(Or alternately the if let construction which still seems a bit weird to me)

(或者可替換的if let結構對我來說仍然有些奇怪)