Zaruya - 4 months ago 23

Python Question

I am trying to create a function which returns the empty slots in this list:

`grid = [[0,0,0,4],[0,0,4,2],[2,4,4,2],[0,8,4,2]]`

The empty slots in this case is those slots with zeroes.

This was my program for it:

`def empty_slots():`

lst = []

for i in grid:

for j in grid:

if j == 0:

lst = lst + [(i,j)]

return lst

However, when I run this program I get an empty list

`[]`

`[(0,0), (0,1), (0,2), (1,0), (1,1), (3,0)]`

Answer

`for i in grid:`

iterates over the *items in grid*, it doesn't iterate over their indices. However, you can get the indices as you iterate over the items of an iterable via the built-in

`enumerate`

function:```
def empty_slots(grid):
return [(i, j) for i, row in enumerate(grid)
for j, v in enumerate(row) if not v]
grid = [[0,0,0,4],[0,0,4,2],[2,4,4,2],[0,8,4,2]]
print(empty_slots(grid))
```

**output**

```
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (3, 0)]
```

Here's the same thing using "traditional" `for`

loops instead of a list comprehension.

```
def empty_slots(grid):
zeros = []
for i, row in enumerate(grid):
for j, v in enumerate(row):
if v == 0:
zeros.append((i, j))
return zeros
```

In this version I use the explicit test of `v == 0`

instead of `not v`

; the latter will test true if `v`

is any "falsey" value, eg, 0, or an empty string, list, tuple, set or dict.

You don't *need* `enumerate`

to do this. You *could* do this:

```
def empty_slots(grid):
zeros = []
for i in range(len(grid)):
row = grid[i]
for j in range(len(row)):
if row[j] == 0:
zeros.append((i, j))
return zeros
```

However, it is considered more Pythonic to iterate directly over the items in an iterable, so this sort of thing is generally avoided, when practical:

```
for i in range(len(grid)):
```

Occasionally you *will* need to do that sort of thing, but usually code like that is a symptom that there's a better way to do it. :)