ADB
ADB

Reputation: 719

Writing multiple nested for...in loops in Swift

Is there a tidier or better way to write the below nested for...in loops in Swift please? Or is using for...in even the correct way to populate my cards?

for cardNumber in 1...3 {
    for cardSymbolIdentifier in 1...3 {
        for cardColorIdentifier in 1...3 {
            for cardShadingIdentifier in 1...3 {
                let card = Card(cardNumber: cardNumber, cardSymbolIdentifier: cardSymbolIdentifier, cardColorIdentifier: cardColorIdentifier, cardShadingIdentifier: cardShadingIdentifier)
                deckOfCards.append(card)
            }
        }
    }
}

It definitely does the job, but I can't find anything in the documentation about writing multiple nested loops.

Many thanks in advance, Andy

Upvotes: 7

Views: 5852

Answers (3)

b m gevariya
b m gevariya

Reputation: 426

If you Do that in a single loop, then it become arithmetically complex

for i in 0..<81 {
    deckOfCards.append(
        Card(cardNumber: i / 27, cardSymbolIdentifier: i/9 % 3, 
             cardColorIdentifier: i/3 % 3, cardShadingIdentifier: i % 3)
    )
}

or

let deckOfCards = (0..<81).map {

    Card(cardNumber: $0 / 27, cardSymbolIdentifier: $0/9 % 3, 
         cardColorIdentifier: $0/3 % 3, cardShadingIdentifier: $0 % 3)
}

In both example - indexing start with 0, so your class init function should shift indexing little
or
add +1 in every parameter before/after passing

Upvotes: 1

Rob Napier
Rob Napier

Reputation: 299703

There is absolutely nothing wrong with your for loops. They are excellent, well-written Swift. The only problem with your code is that it forces deckOfCards to be mutable (var), which may be undesirable. If it is, you could use a map, but I don't consider this particularly better Swift, just slightly different.

let d = (1...3).flatMap { number in
    (1...3).flatMap { symbol in
        (1...3).flatMap { color in
            (1...3).map { shading in
                Card.init(cardNumber: number,
                          cardSymbolIdentifier: symbol,
                          cardColorIdentifier: color,
                          cardShadingIdentifier: shading
                )}}}}

I would probably write it this second way, but only for stylistic reasons. Your for loops are absolutely fine.


Note @user28434's comment below. My original version of this had a major bug (it returned the wrong type). I've been writing Swift since the day it was released. I teach Swift. I teach functional programming in Swift. And I screwed it up when writing it on the fly. I would never have made that mistake with a simple for loop. There's a major lesson in there.

Upvotes: 3

Razi Tiwana
Razi Tiwana

Reputation: 1435

Your code has no optimisation issues at all according to the need but you can make it a little more elegant or swifty (:p)

let values = [1,2,3]

values.forEach { (cardNumber) in
    values.forEach { (cardSymbolIdentifier) in
        values.forEach { (cardColorIdentifier) in
            values.forEach { (cardShadingIdentifier) in

                let card = Card(cardNumber: cardNumber, cardSymbolIdentifier: cardSymbolIdentifier, cardColorIdentifier: cardColorIdentifier, cardShadingIdentifier: cardShadingIdentifier)
                deckOfCards.append(card)
            }
        }
    }
}   

Upvotes: 0

Related Questions