Понимание перечня
Как я могу нарушить понимание списка на основе условия, например, когда найдено число 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
или аналогичный)
Ответы
Ответ 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:
Для тех, кто жалуется, он хакерский и не должен использоваться в рабочем коде: ну, вы правы. Определенно.