#python #python-3.x #list-comprehension
Вопрос:
Я программирую игру Судоку в терминале, я хочу распечатать сетку для консоли с квадратом вокруг нее, как на рисунке ниже. С моим кодом нет никаких проблем, кроме того, что он неэффективен.
Я хотел бы сделать его более эффективным и коротким (с пониманием списка, умножением строк и т. Д.). плата определяется следующим образом: плата = [[_ для _ в диапазоне(9)] для _ в диапазоне(9)]
Это функция, которую я использую:
def Print_Board(board):
print("n-------------------------")
for i in range(9):
for j in range(9):
if board[i][j] is not None:
if j == 0:
print("|", end=" ")
print(f"{board[i][j]} ", end="")
if (j 1) % 3 == 0:
print("|", end=" ")
if (i 1) % 3 == 0:
print("n-------------------------", end=" ")
print()
Комментарии:
1. Если вы не печатаете это тысячи раз, оптимизация не приведет к значительному повышению производительности.
2. Не используйте
_
в качестве имени переменной, если вы на самом деле используете ее значение.3. Я думаю, что sys.stdout работает быстрее, чем обычная печать, хотя разница не будет заметна, если вы не напечатаете чрезвычайно большое количество судоку, чего, я думаю, вы не сделаете. Я согласен с Нитеей.
4. Как правило, минимизируйте количество
print()
s. В идеале создайте полное строковое представление вашего игрового поля и сразу же распечатайте его. Кроме того, поскольку ваши реальные цифры будут другими, вопрос, как он был задан, бесполезен. Сначала вы должны рассмотреть, какая структура данных содержит игровое поле, а затем спросить, как его распечатать.
Ответ №1:
Вы можете создать формат доски и выложить на нее все данные:
bar = '-------------------------n'
lnf = '|' (' {:}'*3 ' |')*3 'n'
bft = bar (lnf*3 bar)*3
print(bft.format(*(el for rw in board for el in rw)))
Конечно, вам нужно создать формат только один раз. После этого это просто отпечаток.
Предложение от JonSG в комментариях, чтобы инкапсулировать это в закрытие:
def make_board_printer():
bar = '-------------------------n'
lnf = '|' (' {:}'*3 ' |')*3 'n'
bft = bar (lnf*3 bar)*3
return (lambda bd:print(bft.format(*(el for rw in bd for el in rw))))
является функцией, которая возвращает функцию принтера платы:
# make a printer:
b_print = make_board_printer()
# then as needed
b_print(board)
Комментарии:
1. Если бы я действительно играл в гольф, планка тоже была бы умножением :-).
2. Вы должны добавить расширенный ответ, который использует замыкание для построения шаблона и возвращает лямбду для печати с ним.
3. Боже, мне так нравится этот ответ. Не только потому, что она короткая и приятная, но и потому, что она концептуально великолепна. Создание шаблона печати, который можно использовать повторно, выводит ввод-вывод из функции форматирования и, что не менее важно, приводит к одному вызову функции печать(). Отличная работа.
Ответ №2:
Ты мог бы сделать это:
def print_board(board):
print("n-------------------------")
for row_num, row in enumerate(board):
print("|", end=" ")
for col_num, item in enumerate(row):
print(item, end=" ")
if (col_num 1) % 3 == 0:
print("|", end=" ")
if (row_num 1) % 3 == 0:
print("n-------------------------", end=" ")
print()
if __name__ == '__main__':
print_board(board=[range(9) for _ in range(9)])
Ответ №3:
Вот (не более читаемое) решение вашей проблемы:
board = [range(1,10) for i in range(9)]
print("-"*25)
for idx, row in enumerate(board):
rowStr = " | ".join([" ".join(map(str, row[i:i 3])) for i in range(0, len(row), 3)])
print(f'| {rowStr} |')
if (idx 1) % 3 == 0:
print("-"*25)
Выход:
-------------------------
| 1 2 3 | 4 5 6 | 7 8 9 |
| 1 2 3 | 4 5 6 | 7 8 9 |
| 1 2 3 | 4 5 6 | 7 8 9 |
-------------------------
| 1 2 3 | 4 5 6 | 7 8 9 |
| 1 2 3 | 4 5 6 | 7 8 9 |
| 1 2 3 | 4 5 6 | 7 8 9 |
-------------------------
| 1 2 3 | 4 5 6 | 7 8 9 |
| 1 2 3 | 4 5 6 | 7 8 9 |
| 1 2 3 | 4 5 6 | 7 8 9 |
-------------------------