Как это очень длинное выражение if можно упростить? - PullRequest
6 голосов
/ 03 ноября 2010

Как можно упростить это if-утверждение?Он ставит знак плюс: http://i.stack.imgur.com/PtHO1.png

Если инструкция выполнена, тогда блок устанавливается в координатах x и y.

for y in range(MAP_HEIGHT):
    for x in range(MAP_WIDTH):
        if (x%5 == 2 or x%5 == 3 or x%5 == 4) and \
            (y%5 == 2 or y%5 == 3 or y%5 == 4) and \
            not(x%5 == 2 and y%5 == 2) and \
            not(x%5 == 4 and y%5 == 2) and \
            not(x%5 == 2 and y%5 == 4) and \
            not(x%5 == 4 and y%5 == 4):
            ...

Ответы [ 6 ]

15 голосов
/ 03 ноября 2010

Это то же самое:

if (x % 5 == 3 and y % 5 > 1) or (y % 5 == 3 and x % 5 > 1): 
12 голосов
/ 03 ноября 2010

По сути, вы строите бинарный паттерн 5х5.Вот четкое выражение этого:

pattern = [[0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0],
           [0, 0, 0, 1, 0],
           [0, 0, 1, 1, 1],
           [0, 0, 0, 1, 0]]

for y in range(MAP_HEIGHT):
    for x in range(MAP_WIDTH):
        if pattern[x%5][y%5]:
           ...

Это очень простой и общий подход, который позволил бы легко изменить шаблон.

7 голосов
/ 03 ноября 2010

Есть два тривиальных исправления:

  • Кэшировать результат x % 5 и y % 5
  • Используйте in или цепочку < для проверки значений:

Кроме того, тест для <= 4 (или < 5) фактически является избыточным, потому что каждое значение lx и ly будет

for y in range(MAP_HEIGHT):
    for x in range(MAP_WIDTH):
        lx = x % 5 # for local-x
        ly = y % 5 # for local-y
        if lx > 1 and y > 1 and \
           not (lx == 2 and ly == 2) and \
           not (lx == 4 and ly == 2) and \
           not (lx == 2 and ly == 4) and \
           not (lx == 4 and ly == 4):

Или вы можете просто сохранить список фактически разрешенных кортежей:

cross_fields = [(2, 3), (3, 2), (3, 3), (3, 4), (4, 3)]

for y in range(MAP_HEIGHT):
    for x in range(MAP_WIDTH):
        if (x % 5, y % 5) in cross_fields:
2 голосов
/ 03 ноября 2010

Опираясь на ответ Конрада, вы можете еще больше упростить его:

for y in range(MAP_HEIGHT):
    for x in range(MAP_WIDTH):
        lx = x % 5 # for local-x
        ly = y % 5 # for local-y
        if (1 < lx < 5 and 1 < y < 5 and 
           (lx, ly) not in ((2, 2), (4, 2), (2, 4), (4, 2))):
1 голос
/ 03 ноября 2010

Второй ответ Конрада: -

cross_fields = [(2, 3), (3, 2), (3, 3), (3, 4), (4, 3)]

for y in range(MAP_HEIGHT):
  for x in range(MAP_WIDTH):
    if (x % 5, y % 5) in cross_fields:

, вероятно, лучший.

Однако я внесу: -

for y in range(MAP_HEIGHT):
  for x in range(MAP_WIDTH):
    lx = x % 5
    ly = y % 5
    if (lx > 1 and ly == 3) or (ly > 1 and lx == 3):
0 голосов
/ 04 ноября 2010

Общим решением для оптимизации логической функции, подобной этой, является карта Карно .Ваша таблица истинности будет желаемой литеральной формой плюс, а строки и столбцы будут вашими модульными тестами.

...