2013-07-19 3 views
4

Я работаю над функцией, которая, учитывая последовательность, пытается найти указанную последовательность внутри списка и затем должна возвращать элемент списка сразу же после завершения этой последовательности.Перезаписывание вложенных операторов if в более Pythonic

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

def sequence_in_list(seq, lst): 
    m, n = len(lst), len(seq) 
    for i in xrange(m): 
     for j in xrange(n): 
      if lst[i] == seq[j]: 
       if lst[i+1] == seq[j+1]: 
        if lst[i+2] == seq[j+2]: 
         return lst[i+3] 

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

+0

Является ли 'seq' строкой или списком в вашем случае? – rkrzr

+0

, если у вас нет другого статута, вы всегда можете «слить», если операторы: 'list [i] == seq [j] и список [i + 1] == seq [j + 1] и список [i + 2] = = seq [j + 2] ' – noisy

+0

Вы хотите получить все элементы, которые появляются после всех вхождений seq в' list'? И, пожалуйста, не используйте встроенные в качестве имени переменной. –

ответ

1

С вами сравнивают последовательные индексы, и предполагая lst и seq одного и того же типа, вы можете использовать нарезку:

def sequence_in_list(seq, lst): 
    m, n = len(lst), len(seq) 
    for i in xrange(m): 
     for j in xrange(n): 
      if lst[i:i+3] == seq[j:j+3]: 
       return lst[i+3] 

Если последовательности а re разного типа, вы должны преобразовать их в общий тип перед выполнением сравнения (например, lst[i:i+3] == list(seq[j:j+3]) будет работать, если seq - это строка и lst - это список).

В качестве альтернативы, если последовательности не поддерживают нарезку, вы можете использовать встроенный в all для проверки нескольких условий:

def sequence_in_list(seq, lst): 
    m, n = len(lst), len(seq) 
    for i in xrange(m): 
     for j in xrange(n): 
      if all(lst[i+k] == seq[j+k] for k in range(3)): 
       return lst[i+3] 

Если вы хотите продлить проверку более 10 показателей, вместо 3, просто изменить range(3) до range(10).

Side Примечание: исходный код будет поднимать IndexError в какой-то момент, так как доступ list[i+1] где i может быть len(list) - 1. Вышеприведенный код не вызывает никаких ошибок, так как нарезка может дать срез короче, чем разница индексов, meainig, что seq[j:j+3] может иметь менее 3 элементов. Если это проблема, вы должны настроить индексы, по которым вы выполняете итерацию.

Последнее замечание: не используйте имя list, поскольку оно затеняет встроенное имя.

+0

Приятный улов на IndexError, я оставил это (возможно, это было неправильно), потому что на этом этапе, когда я продвигаюсь вперед, я знаю, что функция будет анализировать. Позже я бы разрешил это. Оба аргумента являются списком, поэтому ваше первое решение работает красиво, а другое - разум. Благодаря! –

+0

Почему вы выполняете итерацию через 'xrange (n)', а затем нарезаете? – Blender

+0

@Blender Я думаю, что он сосредоточился на управлении вложенными операторами if в соответствии с запросом. Причина, по которой это в моем первоначальном коде, - это славное сочетание попыток, которые я не обязательно понимаю и пишу в течение коротких часов ночи. Код работает просто отлично, если не считать, что все экземпляры 'j' заменены на' i' –

2

Я хотел бы сделать это с помощью генератора и нарезка:

sequence = [1, 2, 3, 5, 1, 2, 3, 6, 1, 2, 3] 
pattern = [1, 2, 3] 

def find_item_after_pattern(sequence, pattern): 
    n = len(pattern) 

    for index in range(0, len(sequence) - n): 
     if pattern == sequence[index:index + n]: 
      yield sequence[index + n] 

for item in find_item_after_pattern(sequence, pattern): 
    print(item) 

И вы получите:

5 
6 

Функция не слишком эффективна и не будет работать для бесконечных последовательностей, но он короткий и общий.

+0

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

0

Вы можете совместить список понимание с нарезкой, чтобы сделать сравнение более читаемым:

n, m = len(lst), len(seq) 
[lst[j+3] for i in range(m-2) for j in range(n-2) if seq[i:i+3] == lst[j:j+3]] 

Конечно, есть более эффективные способы сделать это, но это просто, коротко и питон стиле.

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