F. Pizzuta
F. Pizzuta

Reputation: 107

is there a better way then nested loops?

I have the following code:

(0...engine.rows-1).forEach {row in
        (0...engine.cols-1).forEach {col in
            //print("(\(row),\(col)) state = \(engine.grid[(row,col)])")
            switch engine.grid[(row,col)] {
            case CellState.empty: emptyCount = emptyCount + 1
            case CellState.alive: aliveCount = aliveCount + 1
            case CellState.died: diedCount = diedCount + 1
            case CellState.born: bornCount = bornCount + 1
            }
        }
    }

It looks like filters could do this more efficiently but I don't understand the syntax for a complex object. If not filters is there a better way to do nested loops in swift?

Thanks

Upvotes: 0

Views: 384

Answers (1)

vacawama
vacawama

Reputation: 154603

This looks like Conway's Game of Life.

You are looping through a grid counting the various cell states. Nested loops is the natural way to do this. I would suggest using for in instead of forEach. Also, I would suggest creating a dictionary to hold the counts:

// Create dictionary to hold counts
var counts: [CellState : Int] = [.alive: 0, .died: 0, .born: 0, .empty: 0]

for row in 0 ..< engine.rows {
    for col in 0 ..< engine.cols {
        //print("(\(row),\(col)) state = \(engine.grid[(row,col)])")
        counts[engine.grid[(row, col)]] += 1
    }
}

Another way:

You've given us no information on your Engine class or struct. Depending on the implementation of grid, there might be a way to get an array of all of the cells.

For instance, if you use N-Dimensional Array to create the grid, then you can get all of the cells as an array with grid.data.

struct Engine {
    let rows: Int
    let cols: Int
    var grid: NDimArray<CellState>

    init(rows: Int, cols: Int) {
        self.rows = rows
        self.cols = cols
        self.grid = NDimArray<CellState>(dimensions: rows, cols, initial: CellState.empty)
    } 
}

Setting a cell state would look like:

var engine = Engine(rows: 20, cols: 20)
engine.grid[0, 0] = .alive
engine.grid[0, 1] = .alive

Then the code to count the cells types becomes:

var counts: [CellState : Int] = [.alive: 0, .died: 0, .born: 0, .empty: 0]
engine.grid.data.forEach { cell in counts[cell] += 1 }

Upvotes: 3

Related Questions