Подтвердить что ты не робот

Понимание перечня

Как я могу нарушить понимание списка на основе условия, например, когда найдено число 412?

код:

numbers = [951, 402, 984, 651, 360, 69, 408, 319, 601, 485, 980, 507, 725, 547, 544,
           615, 83, 165, 141, 501, 263, 617, 865, 575, 219, 390, 984, 592, 236, 105, 942, 941,
           386, 462, 47, 418, 907, 344, 236, 375, 823, 566, 597, 978, 328, 615, 953, 345, 399,
           162, 758, 219, 918, 237, 412, 566, 826, 248, 866, 950, 626, 949, 687, 217, 815, 67,
           104, 58, 512, 24, 892, 894, 767, 553, 81, 379, 843, 831, 445, 742, 717, 958, 609, 842,
           451, 688, 753, 854, 685, 93, 857, 440, 380, 126, 721, 328, 753, 470, 743, 527]

even = [n for n in numbers if 0 == n % 2]

Так функционально, это было бы то, что вы можете сделать, это должно делать:

even = [n for n in numbers if 0 == n % 2 and break if n == 412]

Я действительно предпочитаю:

  • однострочный
  • никакие другие причудливые библиотеки, такие как itertools, "чистый python", если это возможно (читайте: решение не должно использовать оператор import или аналогичный)
4b9b3361

Ответ 1

even = [n for n in numbers[:None if 412 not in numbers else numbers.index(412)] if not n % 2] 

Просто взял код F.J. выше и добавил тройку, чтобы проверить, включено ли 412 в список. Еще один "лайнер" и будет работать, даже если 412 нет в списке.

Ответ 2

Используйте функцию поднять StopIteration и list, чтобы поймать ее:

>>> def end_of_loop():
...     raise StopIteration
... 
>>> even = list(end_of_loop() if n == 412 else n for n in numbers if 0 == n % 2)
>>> print(even)
[402, 984, 360, 408, 980, 544, 390, 984, 592, 236, 942, 386, 462, 418, 344, 236, 566, 978, 328, 162, 758, 918]

Для жалующихся это не однострочный:

even = list(next(iter(())) if n == 412 else n for n in numbers if 0 == n % 2)

Для жалующихся хакеров и не следует использовать в производственном коде: ну, ты прав. Определенно.

Ответ 3

Вы можете использовать выражения генератора вместе с itertools.takewhile():

even_numbers = (n for n in numbers if not n % 2)
list(itertools.takewhile(lambda x: x != 412, even_numbers))

Изменить. Я заметил, что не требуется использовать import s. Ну, я оставляю этот ответ здесь в любом случае.

Ответ 4

Если в списке будет 412, вы можете использовать это:

even = [n for n in numbers[:numbers.index(412)] if not n % 2]

Если вы хотите включить 412 в результат, просто используйте numbers[:numbers.index(412)+1] для фрагмента.

Обратите внимание, что из-за среза это будет менее эффективным (по крайней мере, по памяти), чем itertools или для решения цикла.

Ответ 5

Я знаю, что это ОЧЕНЬ СТАРЫЙ пост, однако, поскольку ОП спросил об использовании break внутри list-comprehension, и я также искал что-то подобное, я думал, что опубликую мои выводы здесь для справок в будущем.

При исследовании break я обнаружил малоизвестную функцию iter как iter(callable, sentinel), которая возвращает итератор, который "ломает" итерацию, когда вызываемое значение function равно sentinel > значение.

>>> help(iter)
Help on built-in function iter in module __builtin__:

iter(...)
    iter(collection) -> iterator
    iter(callable, sentinel) -> iterator

    Get an iterator from an object.  In the first form, the argument must
    supply its own iterator, or be a sequence.
    In the second form, the callable is called until it returns the sentinel.

Трудная часть здесь определяет функцию, которая соответствовала бы заданной задаче. В этом случае сначала нам нужно преобразовать заданный list из numbers в iterator, используя x = iter(numbers), который передает внешнюю переменную в функцию lambda.

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

print [i for i in iter(lambda x=iter(numbers): next(x),412) if i %2 == 0]

>>> 
[402, 984, 360, 408, 980, 544, 390, 984, 592, 236, 942, 386, 462, 418,  
 344, 236, 566, 978, 328, 162, 758, 918]

Ответ 6

Синтаксис для отображения списка (включая списки) находится здесь: http://docs.python.org/reference/expressions.html#list-displays

Как вы можете видеть, нет специального синтаксиса while или until. Самое близкое, что вы можете получить, это:

even_numbers = (n for n in numbers if 0 == n % 2)
list(itertools.takewhile(lambda x: x != 412, even_numbers))

(Код, взятый из ответа Свена Марнаха, опубликован, когда я печатал это).

Ответ 7

другое хитрое однострочное решение, позволяющее решить проблему breaking in list comprehension с помощью end условия.

без использования numbers.index(412), может быть, немного быстрее?

even = [n for n in numbers if (False if end or n != 412 else end.append(42)) or not end and not n % 2]

Примечание: это плохая идея. просто для удовольствия :)

как сказал @WolframH:

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