НейроАгент

Как разделить список на равные части в Python

Узнайте несколько способов разделения списков Python на равные части. Изучите срезы списков, itertools.batched(), NumPy и функции-генераторы с примерами кода и сравнением производительности.

Вопрос

Как разбить список на равные части?

Как разбить список произвольной длины на равные по размеру части?

См. также:

НейроАгент

Как разделить список на равные части в Python

Для разделения списка на равные части в Python можно использовать несколько методов, включая срезы списков, itertools.batched() (Python 3.12+), numpy.array_split() или функции-генераторы. Наиболее прямой подход использует срезы списков с методом range() для перебора списка и создания фрагментов указанного размера.

Содержание

Базовый метод срезов списков

Наиболее распространенный подход использует срезы списков с методом range() для создания фрагментов равного размера. Этот метод прост, читаем и работает во всех версиях Python.

python
def split_list_simple(my_list, chunk_size):
    """Разделить список на фрагменты указанного размера"""
    for i in range(0, len(my_list), chunk_size):
        yield my_list[i:i + chunk_size]

# Пример использования
my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
chunk_size = 3
chunks = list(split_list_simple(my_list, chunk_size))
print(chunks)  # [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Эта функция перебирает исходный список и на каждой итерации создает новый фрагмент с помощью среза списка от текущего индекса i до i + chunk_size источник.

Как демонстрирует Python Engineer, этот подход создает пакеты данных из итерируемого объекта в списки равной длины n.

Использование itertools.batched() (Python 3.12+)

Для Python 3.12 и более поздних версий функция itertools.batched() предоставляет наиболее элегантное и эффективное решение:

python
from itertools import batched

my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
chunk_size = 3
chunks = list(batched(my_list, chunk_size))
print(chunks)  # [(1, 2, 3), (4, 5, 6), (7, 8, 9)]

Как объясняет Real Python, itertools.batched() должна быть вашим предпочтительным инструментом для разделения списка Python на фрагменты фиксированного размера. Она включена в стандартную библиотеку начиная с Python 3.12, что делает ее хорошо протестированной, задокументированной, переносимой и эффективной благодаря нативной реализации на C.

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

Подход с NumPy

При работе с приложениями в области науки о данных функция array_split() NumPy предоставляет альтернативу, которая автоматически обрабатывает фрагменты неравного размера:

python
import numpy as np

my_list = [1, 2, 3, 4, 5, 6, 7, 8]
chunk_size = 3
# Вычисляем необходимое количество фрагментов
num_chunks = len(my_list) // chunk_size + (len(my_list) % chunk_size != 0)
res = np.array_split(my_list, num_chunks)
# Преобразуем numpy-массивы обратно в списки Python
chunks = [list(arr) for arr in res]
print(chunks)  # [[1, 2, 3], [4, 5, 6], [7, 8]]

Этот метод особенно полезен, когда размер списка не идеально делится на n источник.

Как отмечает Spark By Examples, numpy.array_split() - еще один простой и эффективный способ разделить список на фрагменты равного размера. Он разделяет массив (или список) на несколько подмассивов равного или почти равного размера.

Функции-генераторы

Функции-генераторы предоставляют способ эффективного использования памяти для обработки больших списков, возвращая фрагменты по одному за раз:

python
from itertools import islice

def chunked_list(lst, chunk_size):
    """Функция-генератор для возврата фрагментов указанного размера"""
    it = iter(lst)
    while True:
        chunk = list(islice(it, chunk_size))
        if not chunk:
            break
        yield chunk

# Пример использования
my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
chunk_size = 3
for chunk in chunked_list(my_list, chunk_size):
    print(chunk)

Этот подход использует itertools.islice для эффективного создания фрагментов без загрузки всего списка в память одновременно источник.

Метод с использованием списковых включений

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

python
def chunkify(lst, chunk_size):
    """Разделить список на фрагменты с использованием спискового включения"""
    return [lst[i:i+chunk_size] for i in range(0, len(lst), chunk_size)]

# Пример использования
my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
chunk_size = 3
chunks = chunkify(my_list, chunk_size)
print(chunks)  # [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Этот однострочный подход лаконичен и эффективен для большинства случаев использования источник.

Сравнение производительности

Различные методы имеют разные характеристики производительности:

Метод Использование памяти Скорость Читаемость Версия Python
itertools.batched() Низкое Быстрая Отличная 3.12+
Списковое включение Среднее Быстрая Хорошая Все
Функция-генератор Низкое Средняя Хорошая Все
NumPy array_split Среднее Быстрая Хорошая С NumPy

Как подчеркивает Real Python, производительность варьируется в зависимости от размера вашего списка и необходимости ленивой оценки.

Обработка крайних случаев

При разделении списков учитывайте эти крайние случаи:

  1. Пустой список - должен возвращать пустой список
  2. Размер фрагмента больше списка - должен возвращать исходный список как единый фрагмент
  3. Размер фрагмента равен нулю - должен вызывать исключение
  4. Отрицательный размер фрагмента - должен вызывать исключение

Вот надежная реализация:

python
def safe_split_list(my_list, chunk_size):
    """Безопасное разделение списка с обработкой ошибок"""
    if chunk_size <= 0:
        raise ValueError("Размер фрагмента должен быть положительным")
    if not my_list:
        return []
    return list(split_list_simple(my_list, chunk_size))

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

Заключение

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

  1. Для Python 3.12+: Используйте itertools.batched() для наиболее элегантного и эффективного решения
  2. Для всех версий Python: Используйте срезы списков с range() для простоты и читаемости
  3. Для приложений в области науки о данных: Рассмотрите NumPy array_split() для обработки больших наборов данных
  4. Для эффективного использования памяти: Используйте функции-генераторы для обработки очень больших списков

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