如何枚举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结构对我来说仍然有些奇怪)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值