Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looping through enum values in Swift [duplicate]

Is it possible to loop through enum values in Swift? Or what is the alternative?

I'm working through Apple's Swift language guide, and I came across this example on enums.

//  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())         }     } } 

Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/us/jEUH0.l

I've tried the following, but the docs say enums in Swift are not assigned underlying integer values like in C, so I'm probably barking up the wrong tree.

Is there a better way solve this problem?

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 } 
like image 966
glaslong Avatar asked Jun 05 '14 13:06

glaslong


People also ask

Can enum have duplicate values?

Two enum names can have same value. For example, in the following C program both 'Failed' and 'Freezed' have same value 0.

Can you loop through an enum?

An enum can be looped through using Enum. GetNames<TEnum>() , Enum.

Can enum inherit Swift?

In Swift language, we have Structs, Enum and Classes. Struct and Enum are passed by copy but Classes are passed by reference. Only Classes support inheritance, Enum and Struct don't.

Can we add constants to enum without breaking existing code?

4) Adding new constants on Enum in Java is easy and you can add new constants without breaking the existing code.


1 Answers

Is there another way? Sure. Is it better, that's for you to decide:

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)") } 

To use this, you will need to make sure that Rank and Suit enums both use Int for their type definitions (ex: enum Rank : Int).

Rank.Ace should equal 1 and the first Suit case should equal 0.

If you want to loop similar to your existing code, you should still make your enums Int types so you can use Rank.King.toRaw() and the like.

The Apple documentation states that enums are not restricted to being 'simply integer values', but certainly can be if you desire them to be.

UPDATE

Idea taken from comment by @jay-imerman, and applicable to 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; } 
like image 183
Erik Avatar answered Oct 08 '22 19:10

Erik