Разделение списка на два по условию в Python

Пройдите тест, узнайте какой профессии подходите и получите бесплатную карьерную консультацию
В конце подарим скидку до 55% на обучение
Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Чтобы разбить список на два — первый с элементами, удовлетворяющими условию, и второй — с элементами, которые условию не удовлетворяют — можно воспользоваться генераторами списков:

Python
Скопировать код
my_list = [1, 2, 3, 4]
четные, нечетные = [x for x in my_list if x % 2 == 0], [x for x in my_list if x % 2 != 0]

В результате четные содержит все четные числа из списка, а нечетные — все нечетные.

Продвинутые стратегии для разбиения

Цикл с одним проходом

Целесообразно разбить список за один проход с использованием цикла for. Этот подход предусматривает распределение каждого элемента на соответствующие списки:

Python
Скопировать код
my_list = [1, 2, 3, 4]
четные, нечетные = [], []
for x in my_list:
    (четные if x % 2 == 0 else нечетные).append(x)

Такой метод ускоряет обработку, избегая двойного обхода списка. Это становится особенно актуально при работе с большими объемами данных.

Использование функции filter

Дополнительные критерии разделения списков настройте с помощью функции filter и лямбда-выражений:

Python
Скопировать код
my_list = range(100)
три_ок, не_три = list(filter(lambda x: x % 3 == 0, my_list)), list(filter(lambda x: x % 3 != 0, my_list))

Создание пользовательских функций для разделения

Создайте собственную функцию, чтобы избежать повторного написания кода:

Python
Скопировать код
def partition(cond, seq):
    return ([x for x in seq if cond(x)], [x for x in seq if not cond(x)])

my_list = range(100)
меньше_пяти, пять_или_больше = partition(lambda x: x < 5, my_list)

Разделение "на лету" с помощью ленивых генераторов

Для работы с очень крупными списками используйте генераторы:

Python
Скопировать код
def lazy_partition(cond, seq):
    a = (x for x in seq if cond(x))
    b = (x for x in seq if not cond(x))
    return a, b

my_list = iter(range(100))
меньше_пятидесяти, пятьдесят_или_больше = lazy_partition(lambda x: x < 50, my_list)

Учет порядка и производительности

Разбиение с учетом порядка

Если важен порядок, используйте collections.deque для эффективного добавления элементов в список:

Python
Скопировать код
from collections import deque

my_list = ['apple', 'banana', 'cherry', 'date']
сладкие, другие = deque(), deque()
for fruit in my_list:
    (сладкие if fruit.startswith('a') else другие).append(fruit)

сладкие = list(сладкие)
другие = list(другие)

Разделение в погоне за производительностью

Для оптимизации производительности можно использовать различные приемы выбора элементов или создавать классы с методом getNext() для более гибкого управления данными.

Создание функции, подобающей Пикассо

Создайте универсальные функции, похожие на "швейцарский нож":

Python
Скопировать код
def flexible_partition(seq, *conds):
    results = [[] for _ in conds]
    for item in seq:
        for i, cond in enumerate(conds):
            if cond(item):
                results[i].append(item)
                break
    return results

Используйте эту функцию следующим образом:

Python
Скопировать код
my_list = range(10)
меньше_пяти, кратные_двум, не_совпали = flexible_partition(
    my_list, 
    lambda x: x < 5, 
    lambda x: x % 2 == 0
)

Визуализация

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

Ученики: [👤🍏, 👤🌭, 👤🍏, 👤🌭]

Условие: у ученика есть яблоко?

Python
Скопировать код
if student.has_apple():
    # Посадка в автобус с яблоками
else:
    # Посадка в автобус с хот-догами

Группы после разделения:

Автобус с яблоками: [🚌👤🍏, 🚌👤🍏] Автобус с хот-догами: [🚌👤🌭, 🚌👤🌭]

Подбор подходящего инструмента для разделения

Метод разбиения списка выбирается в зависимости от задачи: нужно ли учитывать производительность, сохранять порядок или контролировать выделение памяти. В сложных ситуациях полезной может оказаться библиотека python-split.

Изящество в коде не является просто дополнением

Усилия по повышению производительности должны сопровождаться стремлением к читаемости и элегантности кода. Такой код проще понимать, модифицировать и интегрировать в проекты.

Полезные материалы

  1. itertools — функции для создания итераторов — официальная документация Python по itertools.groupby.
  2. API Reference — документация more-itertools — справочник по модулю itertools.
  3. Генераторы списков в Python — Real Python — руководство по генераторам списков.
  4. Функция Filter в Python — DigitalOcean — руководство по использованию функции filter.
  5. Лямбда-выражения в Python — обучающий материал по лямбда-выражениям.