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

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

Также обратите внимание, что не всегда можно разделить исходный список на списки равной длины.

Скачивайте книги ТОЛЬКО на русском языке у нас в телеграм канале: PythonBooksRU
Список из чисел от 1 до 10 не делится равномерно на четыре списка

Давайте приступим!

Разделение списка при помощи итератора

Вот пример того, как разделить список Python на одинаковые по размеру фрагменты с помощью итераторов и ключевого слова yield:

def split_list(lst, chunk_size):
    for i in range(0, len(lst), chunk_size):
        yield lst[i:i+chunk_size]

# Example usage
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9]
chunk_size = 3

for chunk in split_list(lst, chunk_size):
      print(chunk)

Этот код выведет следующее:

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

Давайте рассмотрим код подробнее.

Функция split_list принимает два аргумента: список lst и целое число chunk_size, задающее размер каждого фрагмента. Функция использует цикл for для итераций по списку и выдает подсписок lst, начинающийся с текущего индекса и заканчивающийся текущим индексом плюс размер фрагмента.

Вот пошаговое объяснение того, как работает код:

  1. Функция split_list вызывается со списком lst и размером куска chunk_size.
  2. Цикл for выполняет итерации по списку, начиная с индекса 0. chunk_size определяет шаг range(). Если chunk_size равен 3, первая итерация начнется с индекса 0, вторая – с индекса 3, третья – с 6 и так далее.
  3. На каждой итерации ключевое слово yield строит подсписок lst, начиная с текущего индекса и заканчивая текущим индексом плюс chunk_size. Например, если текущий индекс равен 0, а chunk_size равен 3, то подсписком будет lst[0:3], то есть три элемента lst.
  4. Затем цикл for выполняет итерацию по фрагментам, полученным с помощью split_list, и выводит каждый фрагмент.

Результатом всего этого является список, разбитый на N фрагментов.

А что делает yield?

Разделить список на части при помощи итерационного подхода проще всего. Но если вы новичок в использовании ключевого слова yield и итераторов, это решение может привести вас в замешательство.

В следующем разделе вы узнаете, как сделать то же самое, используя не ключевое слово yield, а списки.

Примечание редакции: лучше все-таки познакомьтесь с yield“Ключевое слово yield в Python”.

Как разделить список при помощи цикла for

Второй подход использует циклы for и списки и поэтому немного удобнее для начинающих, чем предыдущий.

Вот шаги, которые вам необходимо предпринять:

  1. Определите количество фрагментов, на которые вы хотите разбить список. Назовем это число n.
  2. Определите размер фрагментов – chunk_size. Для этого разделите длину списка на n с округлением в меньшую сторон (т.е. в результате деления нужно получить, скажем, не 3.3333, а просто 3).
  3. Используйте функцию range() для создания списка чисел – индексов, с которых должен начинаться каждый фрагмент. Если исходный список состоит из 10 элементов и вы хотите разбить его на 3 части, список начальных индексов будет [0, 3, 6].
  4. Используйте цикл for для итерации по списку начальных индексов и используйте синтаксис list[start:end] для извлечения каждого фрагмента из исходного списка.

Вот код, который реализует эти шаги. Обязательно читайте комментарии, чтобы не терять нить происходящего!

# Установить количество фрагментов
N = 4

# Создать список чисел
my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Создать пустой список для хранения фрагментов
chunks = []

# Перебрать элементы списка по группам из N элементов
for i in range(0, len(my_list), N):
    # Извлечь каждую группу из N элементов в виде подсписка
    chunk = my_list[i:i + N]

    # Добавить подсписок в список фрагментов
    chunks.append(chunk)

# Вывести фрагменты
print(chunks)

Этот код выдает следующий результат:

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

Представление списков может делать то же самое

Когда вы работаете с циклами for, в некоторых случаях для приведения кода в порядок вам может пригодиться list comprehension. Стоит ли использовать представление списка, вопрос дискуссионный. Оно, конечно, сокращает код, но может ухудшить читаемость.

В любом случае, вот предыдущий пример, в котором вместо цикла for используется представление списка:

# Определить входящий список
input_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Определить размер фрагментов
chunk_size = 3

# Создать результирующий список при помощи list comprehension
output_list = [input_list[i:i + chunk_size] for i in range(0, len(input_list), chunk_size)]

# Вывести результирующий список
print(output_list)

Вывод:

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

Как разделить список при помощи цикла while

В предыдущих примерах мы использовали цикл for. Но, конечно, разделить список можно и при помощи цикла while!

Пример:

# Определить список элементов
my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Определить размер фрагментов
chunk_size = 3

# Создать пустой список для хранения фрагментов
chunks = []

# Создать переменную index для отслеживания текущей позиции в списке
index = 0

# Перебирать в цикле, пока index меньше длины списка
while index < len(my_list):
    # Получить подсписок из текущего фрагмента
    chunk = my_list[index:index+chunk_size]

    # Добавить фрагмент в список фрагментов
    chunks.append(chunk)

    # Обновить индекс для следующего фрагмента
    index += chunk_size

# Вывести фрагменты
print(chunks)

Вывод:

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

Это решение создает пустой список для хранения полученных фрагментов, а затем использует цикл while для итерации исходного списка, добавляя каждый фрагмент в список фрагментов. Переменная index используется для отслеживания текущей позиции в списке и обновляется на каждой итерации до следующего фрагмента.

Разделение списка при помощи NumPy

В Python есть популярный математический модуль NumPy. Используя его, можно разделить список на фрагменты при помощи функции array_split(). Эта функция принимает список в качестве первого аргумента и количество фрагментов в качестве второго.

Обратите внимание, что при таком подходе список делится ровно на указанное число частей. Количество элементов во фрагментах может варьироваться.

Например, давайте разобьем список из 10 чисел на 3 части:

import numpy as np

# Определить исходный список
my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Разделить список на части, по 3 элемента в каждой
chunks = np.array_split(my_list, 3)

# Вывести результат
print(chunks)

# Вывод:
# [array([1, 2, 3]), array([4, 5, 6]), array([7, 8, 9, 10])]

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

Спасибо за внимание. Успешного кодинга!

Перевод статьи Artturi Jalli “Python How to Split a List to N Chunks of Even Size”