Автор оригинала: Sathiya Sarathi Gunasekaran.
Вступление
Разбиение строк и списков – это обычная программная деятельность в Python и других языках. Иногда нам приходится разбивать наши данные особым образом, но чаще – на ровные куски.
Язык не имеет встроенной функции для этого, и в этом уроке мы рассмотрим как разбить список на четные куски в Python .
В большинстве случаев это можно сделать с помощью генераторов:
def chunk_using_generators(lst, n): for i in range(0, len(lst), n): yield lst[i:i + n]
Хотя есть и другие интересные способы сделать это, каждый со своими плюсами и минусами!
Разбейте список На Четные куски из N Элементов
Список может быть разделен на основе размера определенного фрагмента. Это означает, что мы можем определить размер куска. Если подмножество списка не помещается в размер определенного фрагмента, заполнители должны быть вставлены вместо пустых держателей элементов. В этих случаях мы будем использовать None
.
Давайте создадим новый файл с именем chunk_based_on_size.py
и добавить следующее содержание:
def chunk_based_on_size(lst, n): for x in range(0, len(lst), n): each_chunk = lst[x: n+x] if len(each_chunk) < n: each_chunk = each_chunk + [None for y in range(n-len(each_chunk))] yield each_chunk print(list(chunk_based_on_size([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], 7)))
Приведенная выше функция chunk_based_on_size()
принимает аргументы: list
для списка и chunk_size
для числа, на которое его нужно разделить. Функция выполняет итерацию по списку с приращением размера блока n
. Ожидается, что каждый кусок будет иметь размер, заданный в качестве аргумента. Если элементов недостаточно для разделения одного размера, оставшиеся неиспользуемые элементы заполняются символом None
.
Запуск этого скрипта возвращает следующий список списков:
$ python3 chunk_based_on_size.py [[1, 2, 3, 4, 5, 6, 7], [8, 9, 10, 11, 12, 13, None]]
Список был разделен на равные куски по 7 элементов каждый.
Python имеет утилиты для упрощения этого процесса. Мы можем использовать функцию zip_longest
из itertools
для упрощения предыдущей функции. Давайте создадим новый файл chunk_using_itertools.py
и добавьте следующий код:
from itertools import zip_longest def chunk_using_itertools(lst): iter_ = iter(lst) return list(zip_longest(iter_, iter_, iter_, iter_, iter_, iter_, iter_)) print(chunk_using_itertools([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]))
Этот код повторяет элементы и возвращает фрагмент желаемой длины – на основе предоставленных вами аргументов. Мы поместили здесь 7 iter_
аргументов. Функция zip_longest()
агрегирует и возвращает элементы из каждой итерации. В этом случае он будет агрегировать элементы из списка, который повторяется 7 раз за один раз. Затем создается множество итераторов, содержащих 7 последовательных элементов, которые затем преобразуются в список и возвращаются.
Когда вы выполните этот фрагмент кода, он приведет к:
$ python3 chunk_using_itertools.py [[1, 2, 3, 4, 5, 6, 7], [8, 9, 10, 11, 12, 13, None]]
Эта более короткая функция производит тот же вход. Однако это гораздо более ограничено, так как нам приходится вручную писать, сколько элементов мы хотим в коде, и немного неудобно просто помещать кучу iter_
s в вызов zip_longest ()
.
Лучшим решением было бы использование генераторов. Давайте создадим новый файл, chunk_using_generators.py
:
def chunk_using_generators(lst, n): for i in range(0, len(lst), n): yield lst[i:i + n] print(list(chunk_using_generators([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], 7)))
Этот генератор дает подсписок, содержащий n
элементов. В конце концов, это дало бы подсписок для каждого куска. Запуск этого кода приводит к такому результату:
$ python3 chunk_using_generators.py [[1, 2, 3, 4, 5, 6, 7], [8, 9, 10, 11, 12, 13]]
Это решение работает лучше всего, если вам не нужно заполнение с помощью None
или иным образом.
Разбейте список На Ровные Куски
В предыдущем разделе мы разделили список на основе размера отдельных фрагментов так, чтобы каждый фрагмент имел одинаковое количество элементов. Есть и другой способ интерпретировать эту проблему. Что мы делаем, когда хотим разбить список не по количеству элементов в каждом фрагменте, а по количеству фрагментов, которые мы хотим создать?
Например, вместо того, чтобы разбивать список на куски, где каждый кусок имеет 7 элементов, мы хотим разбить список на 7 четных кусков. В этом случае мы можем не знать размер каждого куска.
Логика аналогична предыдущим решениям, однако размер блока-это предельное значение длины списка, деленное на количество требуемых блоков. Как и в предыдущих примерах кода, если в куске есть свободные места, они будут заполнены значением filler None
:
import math def chunk_based_on_number(lst, chunk_numbers): n = math.ceil(len(lst)/chunk_numbers) for x in range(0, len(lst), n): each_chunk = lst[x: n+x] if len(each_chunk) < n: each_chunk = each_chunk + [None for y in range(n-len(each_chunk))] yield each_chunk print(list(chunk_based_on_number([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], chunk_numbers=7)))
Мы определяем, сколько списков нам нужно создать и сохранить это значение в n
. Затем мы создаем подсписок для двух элементов одновременно, заполняя выходные данные в случае, если размер нашего фрагмента меньше желаемой длины.
Когда мы выполним этот файл мы увидим:
$ python3 chunk_based_on_number.py [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12], [13, None]]
Как видно из приведенных выше выходных данных, список был разделен на 7 отдельных списков равных размеров на основе предоставленного аргумента chunk_numbers
.
Вывод
В этой статье мы рассмотрели некоторые способы, с помощью которых список можно разбить на куски четного размера и списки на основе пользовательских методов и с помощью встроенных модулей.
Решения, упомянутые в этом учебнике, не ограничиваются теми, которые определены здесь, но есть множество других творческих способов, с помощью которых вы также можете разделить свой список на четные куски.