Чи можна скласти результати в унікальні списки зсередини розуміння?

Контекст розбиває список цілих чисел у власні списки рівних і непарних.

    even = []
    odd = []
    for i in my_list:
        if i % 2 == 0:
            even.append(i)
        else:
            odd.append(i)

Чи є спосіб перетворити вищесказане в хороший, компактний список розуміння ..?

2

6 Відповіді

Не без використання побічних ефектів і відкидання результату. Ви можете це зробити, хоча:

even = []
odd = []
for i in my_list:
    (odd if i % 2 else even).append(i)

Ця проблема загалом називається розбиттям у списку, ви можете знайти деякі рішення , виконуючи пошук SO, але ніхто не набагато чистіший (у Python).

5
додано
Якщо ви дійсно намагаєтеся оптимізувати, як щодо a = [odd.append, even.append]; для мене в моєму списку: a [i% 2] (i) ?
додано Автор nneonneo, джерело
Для випадку i% 2 виявляється, що це повільніше (на моєму комп'ютері), ніж робити 2 розуміння списку (і обчислення i% 2 вдвічі більше разів). Очевидно, це змінюється на більш дорогу функцію розділу. Видобування методів add все ще трохи швидше, хоча.
додано Автор John La Rooy, джерело
Я не намагався оптимізувати, я видаляв надлишковий код. Але чи є індексація швидше, ніж трійковий, якщо? Як щодо oa, ea = odd.append, even.append; для мене в моєму списку: (якщо я% 2 else ea) (i) ?
додано Автор Pavel Anossov, джерело
Що дійсно корисно для швидкості видалення викликів attach . Ось чому два осягання списку так швидко.
додано Автор Pavel Anossov, джерело
Елегантний, мені це подобається!
додано Автор orlenko, джерело

Не без використання побічних ефектів і відкидання результату. Ви можете це зробити, хоча:

even = []
odd = []
for i in my_list:
    (odd if i % 2 else even).append(i)

Ця проблема загалом називається розбиттям у списку, ви можете знайти деякі рішення , виконуючи пошук SO, але ніхто не набагато чистіший (у Python).

5
додано
Якщо ви дійсно намагаєтеся оптимізувати, як щодо a = [odd.append, even.append]; для мене в моєму списку: a [i% 2] (i) ?
додано Автор nneonneo, джерело
Для випадку i% 2 виявляється, що це повільніше (на моєму комп'ютері), ніж робити 2 розуміння списку (і обчислення i% 2 вдвічі більше разів). Очевидно, це змінюється на більш дорогу функцію розділу. Видобування методів add все ще трохи швидше, хоча.
додано Автор John La Rooy, джерело
Я не намагався оптимізувати, я видаляв надлишковий код. Але чи є індексація швидше, ніж трійковий, якщо? Як щодо oa, ea = odd.append, even.append; для мене в моєму списку: (якщо я% 2 else ea) (i) ?
додано Автор Pavel Anossov, джерело
Що дійсно корисно для швидкості видалення викликів attach . Ось чому два осягання списку так швидко.
додано Автор Pavel Anossov, джерело
Елегантний, мені це подобається!
додано Автор orlenko, джерело

Не дуже, ви можете зламати щось, використовуючи побічні ефекти, але це не те, що для розуміння списку

>>> even = []
>>> odd = []
>>> [(odd if i%2 else even).append(i) for i in range(10)]
[None, None, None, None, None, None, None, None, None, None] # it's a waste to make this list
>>> even
[0, 2, 4, 6, 8]
>>> odd
[1, 3, 5, 7, 9]

Трохи менш марнотратні (але важче зрозуміти) це

>>> even = []
>>> odd = [i for i in range(10) if i%2 or even.append(i)]
>>> even
[0, 2, 4, 6, 8]
>>> odd
[1, 3, 5, 7, 9]

Тим не менш, ви можете використовувати умови з першого розуміння списку, щоб спростити свій цикл

even = []
odd = []
for i in my_list:                     # Doesn't make a pointless list of `None`
    (odd if i%2 else even).append(i) 

Якщо my_list дійсно довгий, можливо, варто прив'язувати додавання методів до локальних змінних, щоб зберегти додаткові пошуки (зберігає ~ 30% для переліку 10000)

even = []
odd = []
even_append = even.append
odd_append = odd.append
for i in my_list:
    (odd_append if i%2 else even_append)(i) 

Another speedup is to use i&1 instead of i%2 to select even or odd

4
додано
@ ÓscarLópez, так, це дуже погана продуктивність. Два переліку слів, мабуть, швидше
додано Автор John La Rooy, джерело
Це можна знімати щось без побічних ефектів, але це буде марнотратно. Подивись мою відповідь.
додано Автор Óscar López, джерело

Якщо нечіткі чи навіть відповідні індекси списку, ви можете скористатися розрізанням, щоб зробити це:

>>> my_list=list(range(20))
>>> even,odd=my_list[0::2],my_list[1::2]
>>> even
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
>>> odd
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

Якщо ви просто хочете компактний (і швидкий):

>>> isodd=lambda x: x%2                                                     
>>> random.shuffle(my_list)
>>> even,odd=[x for x in my_list if not isodd(x)],[x for x in my_list if isodd(x)]
>>> even
[12, 6, 2, 18, 14, 0, 10, 16, 8, 4]
>>> odd
[17, 1, 19, 11, 15, 5, 9, 13, 7, 3]
3
додано
Це буде працювати тільки в тому випадку, якщо список буде відсортовано, він не буде працювати для загального випадку, коли предикат є чимось складнішим, ніж навіть/непарним.
додано Автор Óscar López, джерело

Не самий короткий (найприємніший) список понять у світі, але, принаймні, це побічний ефект, він написаний у стилі функціонального програмування, не використовуючи append() . Тут ти йдеш:

lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

even, odd = [[x for x in y if x is not None] for y in zip(*((None, e) if e % 2 else (e, None) for e in lst))]

even
=> [2, 4, 6, 8, 10]

odd
=> [1, 3, 5, 7, 9]
1
додано
Зручно, у вас немає 0 в lst :) Вам знадобиться x не є ніким , щоб його заховати :)
додано Автор John La Rooy, джерело
@gnibbler заплутаний, er, фіксований! :)
додано Автор Óscar López, джерело

Одинарний прохід:

my_list=[i for i in range(50)]
lists=[[], []]
[ lists[x % 2].append(x) for x in my_list ]
print lists[0]
print lists[1]
1
додано
@Зак, це є марнотратним. Ось чому вам слід дотримуватися простого циклу for для цього шаблону
додано Автор John La Rooy, джерело
Дійсна точка;) Однак, здавалося, марно, щоб двічі проходити повторення в тому ж списку, щоб просто розбити непарні та рівноправні - особливо, якщо список величезний.
додано Автор Zack Yoshyaro, джерело
ІТ КПІ - Python
ІТ КПІ - Python
625 учасників

Канал обговорень про всякі штуки зі світу пайтону. Прохання: 0. мати повагу одне до одного; 1. не матюкатися в сторону людей; 2. не захламляти тред повідомленнями по одному слову;