3

I want to go through just a section of a 2D list, rather than the whole thing. Here's essentially what it is I want to do: Let's say the user inputs the coordinates [1,1] (so, row 1 column 1) If I have the 2D list:

[[1,3,7],
[4,2,9],
[13,5,6]]

Then I want to iterate through all the elements adjacent to the element at [1,1]

Furthermore, if the element is at a corner or the edge of the 2D list, (so basically if the user enters [0,0], for example) then I want to just want to get back the elements at [0,0], [0,1], [1,0], and [1,1]

So essentially I just want elements adjacent to a specific to a certain point in the 2D array.

Here's what I've done so far: I've made it so that it assigns 4 variables at the start of the code: starting_row, ending_row, starting_column, and ending_column. These variables are assigned values based off of which coordinates the user wants to input (if they the row is 0 or len(list) then the for loop runs accordingly. The same goes for the columns). Then, I use a nested for loop to go through every element

for row in range(row_start, row_end+1):
        for column in range(column_start, column_end+1):
            print(lst[row,column])            

Only thing is, it doesn't seem to work correctly and often outputs the whole entire 2D list when enter a list size of more than 3x3 elements (all the lists will be square lists)

rpanai
  • 12,515
  • 2
  • 42
  • 64
EkLuthra
  • 147
  • 1
  • 9
  • 1
    for standard list you have to use `lst[row][column]` instead of `lst[row,column]` – furas Oct 26 '19 at 00:28
  • using `range()` and later `lst[row][column]` you can get error `index out of the range`. Better slice list - `rows = lst[(row-1):(row+2)]`. Even if you use wrong indexes you don't get error - and you don't have to check if you in `[0][0]`. – furas Oct 26 '19 at 00:34
  • Also you can use NumPy array and have vertical slicing https://stackoverflow.com/questions/17277100/python-slicing-a-multi-dimensional-array – 4xy Oct 26 '19 at 00:42

1 Answers1

4

You can slice the list of lists according to the given row and column. For the lower bounds, use max with 0 to avoid slicing with a negative index, but not so for the upper bounds since it is okay for the stopping index of a slice to be out of the range of a list:

def get_adjacent_items(matrix, row, col):
    output = []
    for r in matrix[max(row - 1, 0): row + 2]:
        for i in r[max(col - 1, 0): col + 2]:
            output.append(i)
    return output

or, with a list comprehension:

def get_adjacent_items(matrix, row, col):
    return [i for r in matrix[max(row - 1, 0): row + 2] for i in r[max(col - 1, 0): col + 2]]

so that given:

m = [[1, 3, 7],
     [4, 2, 9],
     [13, 5, 6]]

get_adjacent_items(m, 0, 0) returns: [1, 3, 4, 2]

get_adjacent_items(m, 1, 1) return: [1, 3, 7, 4, 2, 9, 13, 5, 6]

get_adjacent_items(m, 2, 1) returns: [4, 2, 9, 13, 5, 6]

get_adjacent_items(m, 2, 2) returns: [2, 9, 5, 6]

blhsing
  • 91,368
  • 6
  • 71
  • 106
  • Hmm. It does work. That's interesting. I've never seen the `i for r in...` loop before. I'm guessing you're adding 2 to the rows and columns after the colons because your last element in each row/column will be 1 after the element itself (it's exclusive, so we do +2 instead of +1). Correct me if I'm wrong. Could this be written not in one line (I don't want the answer for this, maybe just a hint). – EkLuthra Oct 26 '19 at 01:31
  • 1
    Yes you're right about why 2 is needed to be added to the stopping index of the slices (it's exclusive). I've updated my answer with the equivalent implementation with nested `for` loops. – blhsing Oct 26 '19 at 01:36