Вы по-прежнему будете каким-то образом требовать вложенных циклов для циклов, поскольку вы перебираете список списков, но вы могли бы немного упростить логику, используя их списки.
def solver(matrix):
mx = [[v if v else 'x' for v in row] for row in matrix]
mxx = [[v1 if v2 else 'x' for v1, v2 in zip(row1, row2)] for row1, row2 in zip(mx[1:], matrix)]
return mx[:1] + mxx
Сначала я перебираю матрицу и заменяю 0 на "x"
s в новой матрице mx
.
mx = [[v if v else 'x' for v in row] for row in matrix]
Это просто понимание вложенного списка, в котором мы оперируем каждым элементом в строке, каждой строкой в матрице. ... if ... else ...
- это просто ваш классический троичный оператор. Если v
выполнено (в нашем случае это не ноль), то оно вычисляется до значения перед «if», в противном случае оно оценивается до значения после «else» - в данном случае 'x'
.
Затем я повторяю процесс, но смещая строки на одну, чтобы я мог проверить, является ли вышеприведенный элемент "x"
.
mxx = [[v1 if v2 else 'x' for v1, v2 in zip(row1, row2)] for row1, row2 in zip(mx[1:], matrix)]
Здесь есть что сломать. Давайте начнем с «снаружи» и продолжим наш путь.
... for row1, row2 in zip(mx[1:], matrix)
Это сжатие новой матрицы, смещенной на единицу (используя [1:]
обозначение среза), с исходной матрицей. Таким образом, он возвращает итеративно функционально эквивалентный следующий список:
[(mx_row1, matrix_row0), (mx_row2, matrix_row1), (mx_row3, matrix_row2), ...]
Это позволяет нам извлекать данную строку и строку над ней одновременно, как row1
и row2
. Тогда другая половина -
[v1 if v2 else 'x' for v1, v2 in zip(row1, row2)]
- повторяет аналогичный процесс для каждого элемента в строке, а не для строки в матрице. Мы не смещаем элементы в каждой строке, как мы смещаем строки матрицы mx
, но в остальном логика идентична. Затем мы снова сравниваем с нашим троичным оператором, чтобы увидеть, является ли вышеуказанный элемент 0
, и, если это так, оценим 'x'
. Мы могли бы легко изменить это, чтобы сравнить каждый элемент каждой строки от mx
до 'x'
вместо matrix
до 0
, но я решил отразить понимание первого списка.
Получив эту новую матрицу mxx
, я просто добавляю к первой строке mx
, потому что мы эффективно пропускаем эту строку, когда смещаем наше сравнение. В результате получается матрица со всеми 0
с и элементами ниже, замененными на "x"
с.
В соответствии с разъяснениями в комментариях, если вы хотите отметить "x"
, если любой из вышеперечисленных элементов равен 0
, а не только непосредственно указанному выше, вы можете сделать это, взяв часть этого столбца матрицы и использование встроенного all()
, чтобы увидеть, есть ли 0
. Пересмотренный код ниже
def solver(matrix):
return [[v if all(col) else 'x' for v, col in zip(row, zip(*matrix[:idx]))] for idx, row in enumerate(matrix, 1)]