2013-12-05 2 views
12

Мне нужен лучший способ сделать это. Я новичок в программировании, но я знаю, что это очень неэффективный способ сделать это, и что для этого мне нужна функция, я просто не знаю, как это сделать. какие-либо предложения? Я ОЧЕНЬ благодарен за любую помощь!Python - Любой способ избежать нескольких операторов if внутри друг друга в for-loop?

for H in range(0,len(a_list)): 
    if a_list[H] > list4[0]: 
     list5 = [number_list[i]] 
     if function(list1,list5) == list1[1]: 
      if function(list2,list5)== list2[1]: 
       if function(list3,list5)== list3[1]: 
        if function(list4,list5)== list4[1]: 
         list5.append(input('some input from the user')) 
         other_function(list5) 
         if list5[1]== 40: 
          print ('something something') 
          break out of EVERY loop 
         else: 
          for H in range(0,len(a_list)): 
           if a_list[H] > list5[0]: 
            list6 = [number_list[i]] 
            if function(list1,list6) == list1[1]: 
             if function(list2,list6)== list2[1]: 
              if function(list3,list6)== list3[1]: 
               if function(list4,list6)== list4[1]: 
                if function(list5,list6)== list5[1]: 
                list6.append(input('some input from theuser')) 
                other_function(list6) 
                 if list6[1]== 40: 
                  print ('something something') 
                   break out of EVERY loop 
                 else: 
                  etc. (one extra comparison every time) 
+2

Перепишите их как 'if X == Y и Z == W и ...' в том же порядке? – favoretti

+4

Этот _really_ ваш код, или просто что-то сделанное, чтобы показать много вложенного кода? Каким должен быть код? Это поиск данных? Выполняет ли это вычисление? В зависимости от ответа на эти вопросы реальным ответом может быть изменение структуры данных, чтобы избежать необходимости всех условных проверок. –

+0

Может быть, совершенно другой и лучший способ сделать то, что вы пытаетесь сделать ... Не могли бы вы добавить описание предполагаемой функции (входы/выходы)? – jpwagner

ответ

3

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

Учитывая это, мы сначала меняем list1, list2, list3, ... в список списков (с индексом 0,1,2,3 вместо 1,2,3,4). Кроме того, не называйте это list, потому что это полезное имя для того, что уже полезно. lst довольно популярен в Python. Я также собираюсь изменить list5 в lstA и list6 на lstB, потому что 5 и 6 больше не имеют смысла.

Теперь мы имеем это:

for H in range(0,len(a_list)): 
    if a_list[H] > lst[3][0]: 
     lstA = [number_list[i]] 
     if function(lst[0],lstA) == lst[0][1]: 
      if function(lst[1],lstA)== lst[1][1]: 
       if function(lst[2],lstA)== lst[2][1]: 
        if function(lst[3],lstA)== lst[3][1]: 
         lstA.append(input('some input from the user')) 
         other_function(lstA) 
         if lstA[1]== 40: 
          print ('something something') 
          break out of EVERY loop 
         else: 
          for H in range(0,len(a_list)): 
           if a_list[H] > lstA[0]: 
            lstB = [number_list[i]] 
            if function(lst[0],lstB) == lst[0][1]: 
             if function(lst[1],lstB)== lst[1][1]: 
              if function(lst[2],lstB)== lst[2][1]: 
               if function(lst[3],lstB)== lst[3][1]: 
                if function(lstA,lstB)== lstA[1]: 
                lstB.append(input('some input from theuser')) 
                other_function(lstB) 
                 if lstB[1]== 40: 
                  print ('something something') 
                   break out of EVERY loop 
                 else: 
                  etc. (one extra comparison every time) 

Теперь это более очевидно, что мы в основном делаем то же самое в четыре раза.


Если вам нужно сделать то же самое несколько раз, подумайте о петлях.

Мы будем менять блоки на циклы. Мы также будем использовать переменный флаг для отслеживания того, не удалось что-то во время тестирования нашей логики, и использовать логику «если он не работает, пропустить вещи», а не «если это работает, делать такие вещи»

for H in range(0,len(a_list)): 
    if a_list[H] > lst[3][0]: 
     continue #reducing indent levels by negating the check: 
       #quit on failure instead of work on success 

    lstA = [number_list[i]] 

    quit = False 

    for j in range(4): 
     if function(lst[j],lstA) != lst[j][1]: #testing FALSEHOOD 
      quit = True 
      break #the j loop only 

    if quit: 
     continue #reducing indent levels by negating the check 

    lstA.append(input('some input from the user')) 
    other_function(lstA) 
    if lstA[1]== 40: 
     print ('something something') 
     break #out of EVERY loop 
    #else: #don't need the else because we broke 

    for H in range(0,len(a_list)): 
     if not a_list[H] > lstA[0]: 
      continue #reducing indent levels by negating the check 

     lstB = [number_list[i]] 

     for j in range(4): 
      if function(lst[j],lstB) != lst[j][1]: #testing FALSEHOOD 
       quit = True; 
       break #to the H loop 
     if not quit and function(lstA,lstB)== lstA[1]: #combining two checks 
      lstB.append(input('some input from theuser')) 
      other_function(lstB) 
      if lstB[1]== 40: 
       print ('something something') 
       break #out of EVERY loop 
      else: #at this point I'm lost and can't refactor 
       etc. (one extra comparison every time) 

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

Неисправный флаг работает, но не очень изящный. Есть преувеличенное высказывание: "... if you need more than 3 levels of indentation, you're screwed anyway, and should fix your program." Прочитайте это как: Если у вас много уровней отступов (и некоторые языки требуют больше, чем другие), вы должны подумать о том, можете ли вы переместить часть логики в функцию.

Мы также переместим некоторую повторяющуюся логику в функцию проверки.

(Наконец, я думаю, что это ошибка, что ваша вторая для цикла вложен в ваш первый. Так как они имеют один и тот же итератор переменную H, я думаю, что это вызовет бесконечный цикл. Таким образом, я установил, что.)

#returns FALSE if a check fails, unlike the `quit` variable 
def checker(lst, lstA): 
    for i in range(4): 
     if function(lst[i],lstA) != lst[i][1]: #testing FALSEHOOD 
      return False; 
    return True; 


def main(???): 
    for H in range(0,len(a_list)): 
     if a_list[H] > lst[3][0]: 
      continue 

     lstA = [number_list[i]] 

     if not checker(lst,lstA): 
      continue 

     lstA.append(input('some input from the user')) 
     other_function(lstA) 
     if lstA[1]== 40: 
      print ('something something') 
      return #break out of EVERY loop 

    for H in range(0,len(a_list)): 
     if not a_list[H] > lstA[0]: 
      continue 

     lstB = [number_list[i]] 

     if checker(lst,lstB) and function(lstA,lstB) == lstA[1]: 
      lstB.append(input('some input from theuser')) 
      other_function(lstB) 
      if lstB[1]== 40: 
       print ('something something') 
       return # break out of EVERY loop 
      else: #at this point I'm lost and can't refactor 
       etc. (one extra comparison every time) 
+0

спасибо !! Я смог решить свою проблему через часть того, что вы предложили! Серьёзно, я мог бы поцеловать тебя прямо сейчас ... И запомните вам, что вы были очень образовательными, мне стало намного легче, кто ничего не знал о программировании! – user2966098

+0

Если я хочу что-то напечатать, когда контрольная панель возвращает false для каждой итерации, как я могу это сделать? :) – user2966098

+0

Используйте 'else'. Или вложенный 'if', второй раз. – leewz

12

Используйте all() function протестировать несколько родственных состояний:

if all(function(lst, list5) == lst[1] for lst in (list1, list2, list3, list4)): 

и

if all(function(lst, list6) == lst[1] for lst in (list1, list2, list3, list4, list5)): 

Подобно вложенным if заявления, all() будет короткого замыкания; return False, как только любой из тестов завершится с ошибкой.

Кроме того, перебирать списки непосредственно, вместо генерации диапазона индексов. Если вы используете break, вам не нужно использовать else, удалив еще один уровень отступов.

Вы можете удалить другой уровень путем фильтрации a_list:

for H in filter(lambda H: H > list4[0], a_list): 

вместе это снижает вложенности до:

for H in filter(lambda H: H > list4[0], a_list): 
    list5 = [number_list[i]] 
    if all(function(lst, list5) == lst[1] for lst in (list1, list2, list3, list4)): 
     list5.append(input('some input from the user')) 
     other_function(list5) 
     if list5[1]== 40: 
      print ('something something') 
      break # out of EVERY loop 

     for J in filter(lambda J: J >list5[0], a_list): 
      if all(function(lst, list6) == lst[1] for lst in (list1, list2, list3, list4, list5)): 
      list6.append(input('some input from theuser')) 
      other_function(list6) 
      if list6[1]== 40: 
       print ('something something') 
       break # out of EVERY loop 

      # continue here 

Предположительно ваши break заявления исключения фактического использования (raise CustomException() и try:, except CustomException: # break out of all the loops fast), поскольку обычный break остановит только текущий цикл.

Если вы постоянно добавлять дополнительные списки и вложенность, вы, вероятно, хотите использовать список, чтобы держать все эти вложенные списки, а затем просто добавить к наружному листу:

class EndLoops(Exception): pass 

stack = [[number_list[0]]] 
try: 
    for i in number_list[1:]: 
     for H in filter(lambda H: H > stack[-1][0], a_list): 
      stack.append([i]) 
      if all(function(lst, stack[-1]) == lst[1] for lst in stack[:-1]): 
       stack[-1].append(input('some input from the user')) 
       other_function(stack[-1]) 
       if stack[-1][1] == 40: 
        print ('something something') 
        raise EndLoops 
except EndLoops: 
    pass # broken out of outer loop 

и вдруг все вложенности пошли; вместо этого вы переместили вложенность в список списков stack.

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

+0

Большое спасибо, я посмотрю, смогу ли я заставить его работать с этим! – user2966098

Смежные вопросы