#python #python-3.x
#python #python-3.x
Вопрос:
У меня возникла проблема, когда мне приходится перебирать список размером 5×5 в списке. Итак, я создал список внутри списка, в котором все элементы равны 0 для удобства:
lst = [[0 for x in range(6)] for y in range(6)]
print(lst)
что даст мне:
[[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0]]
Я должен иметь возможность начинать с любой координаты в этом вложенном списке, например, lst[3] [2], затем продолжайте проверять каждую координату lst [3] [3], lst [3] [4], lst [3] [4], lst [4][0], … и так далее, пока я не достигну максимума, который равен st [4] [4], после чего мне нужно вернуться к lst [4] [3], lst [4] [2], lst [4] [1], … пока он не достигнет lst [0] [0] после чего я должен выполнить повторный цикл. Это похоже на бесконечный цикл, в котором я начинаю с определенного места, а затем бесконечно перебираю туда и обратно, пока не скажу ему остановиться.
Я могу выполнить вложенный цикл, но он останавливается на lst[4],[4]:
for x in range(len(lst)):
for y in range(len(lst)):
lst[x][y] = do something
Я могу настроить диапазоны, чтобы они начинались с определенной координаты, но я не могу создать бесконечный цикл, который будет продолжать цикл взад и вперед. Я также попытался добавить цикл while:
while True:
for x in range(len(lst)):
for y in range(len(lst)):
lst[x][y] = do something
но после того, как он полностью зацикливается, он начинается сначала с lst[0][0], а не с lst [4][3] . Не говоря уже о том, что он начинается с начальной точки, которую я выбрал.
Комментарии:
1. Во-первых, максимальное значение равно [5][5], а не [4][4]. Во-вторых, вы хотите изменить направление в конце, а не цикл. Правильно ли это?
2. Да, я хотел бы изменить направление в конце. Прошу прощения за [4] [4] Я неправильно создал цикл внутри цикла
Ответ №1:
С местоположением легче работать, если вы рассматриваете местоположение в массиве как линейное местоположение и вычисляете x, y:
import random
MAX_X,MAX_Y = 3,3
L = [[0] * MAX_Y for _ in range(MAX_X)]
# Initial array values
cnt = 1
for x in range(MAX_X):
for y in range(MAX_Y):
L[x][y] = cnt
cnt = 1
print(L)
# Pick a linear starting location
cur = random.randrange(MAX_X * MAX_Y)
d = 1 # direction to advance
while True:
x,y = divmod(cur,MAX_Y) # compute x,y from linear location
print(f'{x},{y} = {L[x][y]}')
cur = d # advance in direction
# if went off either end, reverse direction
if cur == MAX_X * MAX_Y or cur == -1:
d = -d
cur = 2 * d # stepped one off the wrong way, so go back two.
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
2,0 = 7
2,1 = 8
2,2 = 9
2,1 = 8
2,0 = 7
1,2 = 6
1,1 = 5
1,0 = 4
0,2 = 3
0,1 = 2
0,0 = 1
0,1 = 2
0,2 = 3
1,0 = 4
1,1 = 5
1,2 = 6
2,0 = 7
2,1 = 8
2,2 = 9
2,1 = 8
2,0 = 7
...
Другой вариант, если 2D-матрица не является жестким требованием, а массив доступен только для чтения, — это развернуть цикл. Создайте единый массив со значениями из 2D-массива в порядке возрастания, затем в порядке убывания. Если вы хотите начать с определенного местоположения в массиве, вычислите начальное местоположение и срежьте предыдущие значения до конца массива:
import random
import itertools
MAX_X,MAX_Y = 3,3
L = [[0] * MAX_Y for _ in range(MAX_X)]
# Initial array values (same as before)
cnt = 1
for x in range(MAX_X):
for y in range(MAX_Y):
L[x][y] = cnt
cnt = 1
print(L)
linear = sum(L,[]) # Make a 1D array joining all the rows.
# Pick a starting X/Y location
start_x = random.randrange(MAX_X)
start_y = random.randrange(MAX_Y)
# compute its linear location
cur = start_x * MAX_Y start_y
# slice elements before starting location to end of the list
# and include the reversed array values as well.
unrolled = linear[cur:] linear[-2:0:-1] linear[:cur]
print(unrolled)
# cycle through the list endlessly
for n in itertools.cycle(unrolled):
print(n)
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, 3, 4]
5
6
7
8
9
8
7
6
5
4
3
2
1
2
3
4
5
6
...
Ответ №2:
Похоже, это работает:
import time
def showgrid(lst):
for i in lst:
for j in i:
print(str(j).center(3),end=' ')
print()
print()
lst = [[0 for x in range(3)] for y in range(3)] # array all zeros
d = 1 # direction, start forward
x,y = 1,1 # start mid grid
ctr = 1 # data for array position
while True:
lst[y][x] = ctr # set array data
x =d # next cell
if x == len(lst[0]) or x == -1: # reached end of row
y =d # next row
x = len(lst[0])-1-x d # move to other end of row
if y == len(lst) or y == -1: # end or array
d=-d # switch direction
y =d # start back
x = len(lst[0])-1-x d # revert other end of row
ctr =1
showgrid(lst)
time.sleep(.1)
Вывод
0 0 0
0 1 0
0 0 0
0 0 0
0 1 2
0 0 0
0 0 0
0 1 2
3 0 0
0 0 0
0 1 2
3 4 0
0 0 0
0 1 2
3 4 5
0 0 0
0 1 2
3 6 5
0 0 0
0 1 2
7 6 5
0 0 0
0 1 8
7 6 5
0 0 0
0 9 8
7 6 5
0 0 0
10 9 8
7 6 5
Ответ №3:
В отличие от других подходов, я решил сначала получить диапазон всех возможных x и y (включая цикл и обратный цикл), используя get_range_positions
функцию. После этого я выполнил другую функцию для получения необходимых значений, учитывая начальную позицию для x и y, и эту функцию я вызвал get_coordinates
.
В конце я просматриваю список, учитывая полученные значения x
и y
.
def get_range_positions(len_first_list,
len_second_list):
result = []
# loop
for a in range(len_first_list):
for b in range(len_second_list):
result.append((a,b))
# reverse loop, but we don't want
# the last and first value again
f = 0
l = len(result) - 2
for i in result[l:f:-1]:
result.append(i)
return result
def get_coordinates(start_x,start_y, range_positions):
# finding out where start_x and start_y is in range_positions
start = range_positions.index((start_x,start_y))
# Return X and Y from (start_x,start_y) until the end
for i in range_positions[start:]:
yield i[0], i[1]
# Return X and Y for the entire result_changes, forever.
while True:
for i in range_positions:
yield i[0], i[1]
lst = [[x for x in range(6)] for y in range(6)]
range_positions = get_range_positions(6,6)
print(range_positions)
for x, y in get_coordinates(start_x=0,
start_y=0,
range_positions=range_positions):
lst[x,y] = do something
Ответ №4:
Вы могли бы создать плоскую одномерную последовательность индексов для вашего 2D-списка:
indices1D = [(i, j) for i in range(NROWS) for j in range(NCOLUMNS)]
Чтобы иметь возможность вернуться назад, прикрепите обратные индексы и используйте itertools.cycle()
, чтобы повторять это вечно:
import itertools
indices = itertools.cycle(indices1d indices1d[::-1][1:-1])
[1:-1]
выше указано, чтобы сократить / избежать дублирования точек поворота.
Чтобы начать с заданного индекса, вы могли бы использовать itertools.islice
:
start_position = i_start * NCOLUMNS j_start
for i, j in itertools.islice(indices, start_position, None):
print(lst[i][j])
Собрать все это вместе:
import itertools
def back_n_forth(seq, i_start, j_start):
indices1d = [(i, j) for i in range(NROWS) for j in range(NCOLUMNS)]
indices = itertools.cycle(indices1d indices1d[::-1][1:-1])
start_position = i_start * NCOLUMNS j_start
for i, j in itertools.islice(indices, start_position, None):
yield seq[i][j]
# some random 2d list
NROWS = 3
NCOLUMNS = 2
lst = [
[chr(ord('a') i) str(j) for j in range(NCOLUMNS)]
for i in range(NROWS)
]
for row in lst:
print(*row)
print()
# look at the first few items in the infinite sequence
for x in itertools.islice(back_n_forth(lst, 1, 0), 20):
print(x, end=' ')
Вывод
a0 a1
b0 b1
c0 c1
b0 b1 c0 c1 c0 b1 b0 a1 a0 a1 b0 b1 c0 c1 c0 b1 b0 a1 a0 a1