Why can't I slice a column as I can a row?

Viewed 137

I have a Sudoku Board as this list,

board = [   ['.', 2, '.', '.', '.', 4, 3, '.', '.'], 
            [9, '.', '.', '.', 2, '.', '.', '.', 8], 
            ['.', '.', '.', 6, '.', 9, '.', 5, '.'], 
            ['.', '.', '.', '.', '.', '.', '.', '.', 1], 
            ['.', 7, 2, 5, '.', 3, 6, 8, '.'], 
            [6, '.', '.', '.', '.', '.', '.', '.', '.'], 
            ['.', 8, '.', 2, '.', 5, '.', '.', '.'], 
            [1, '.', '.', '.', 9, '.', '.', '.', 3], 
            ['.', '.', 9, 8, '.', '.', '.', 6, '.']    ]

I can easily check a certain value is present in a row or not so effortlessly by, value in board[row][:] but I can't do the same thing for a column. For example, when I write value in board[:][col] it somehow picks the row, indexed with the value col and then tries to find the specified value.

For example, print(board[6][:]) gives ['.', 8, '.', 2, '.', 5, '.', '.', '.'] (7th row) and print(board[:][2]) gives ['.', '.', '.', 6, '.', 9, '.', 5, '.'] (3rd row). I'm really confused why it is the case.

My question is, is there an equivalent syntax of board[row][:] for a column? And more importantly why board[:][col] doesn't work?

3 Answers

The equivalent syntax is zip(*board)[2][:]:

>>> zip(*board)[2][:]
('.', '.', '.', '.', 2, '.', '.', '.', 9)
>>> 2 in zip(*board)[2][:]
True

See documentation for zip().

Your method doesn't work because board[:] means "all rows", i.e. the same thing as board. So board[:][2] is equivalent to board[2]. You don't need the [:] part in value in board[row][:] either.

To be clear, the [:] syntax is commonly used for copying, as @VPfB mentioned. Since you are only reading the list, it doesn't matter (and in fact slighly less efficient because you are creating an in-memory copy of the whole board).

Your confusion comes on how indexing works in Python. This might clear it up a bit:

board = [
    [".", 2, ".", ".", ".", 4, 3, ".", "."],
    [9, ".", ".", ".", 2, ".", ".", ".", 8],
    [".", ".", ".", 6, ".", 9, ".", 5, "."],
    [".", ".", ".", ".", ".", ".", ".", ".", 1],
    [".", 7, 2, 5, ".", 3, 6, 8, "."],
    [6, ".", ".", ".", ".", ".", ".", ".", "."],
    [".", 8, ".", 2, ".", 5, ".", ".", "."],
    [1, ".", ".", ".", 9, ".", ".", ".", 3],
    [".", ".", 9, 8, ".", ".", ".", 6, "."],
]

first = board[0]
second = board[0][0]

# Prints the row, as expected.
print(first)  # ['.', 2, '.', '.', '.', 4, 3, '.', '.']

# Prints the value of the INDEX in the row[0].
print(second)  # .

# Finds the actual column values by iterating through the values in index 0 of all the rows.
column = []
for row in board:
    column.append(row[0])  # Row number 0.

print(column) # ['.', 9, '.', '.', '.', 6, '.', 1, '.']

If you are using NumPy, you can access column values easily.

>> board = numpy.array([
    [".", 2, ".", ".", ".", 4, 3, ".", "."],
    [9, ".", ".", ".", 2, ".", ".", ".", 8],
    [".", ".", ".", 6, ".", 9, ".", 5, "."],
    [".", ".", ".", ".", ".", ".", ".", ".", 1],
    [".", 7, 2, 5, ".", 3, 6, 8, "."],
    [6, ".", ".", ".", ".", ".", ".", ".", "."],
    [".", 8, ".", 2, ".", 5, ".", ".", "."],
    [1, ".", ".", ".", 9, ".", ".", ".", 3],
    [".", ".", 9, 8, ".", ".", ".", 6, "."],
])

>> board[:,0]
>> array([".", 9, ".",".",".",6,".",1,"."])
Related