СПИСКОВЫЕ ВКЛЮЧЕНИЯ (LIST COMPREHENSION)
Довольно часто мы сталкиваемся с задачей создания списка путем итерирования по чему-либо, будь то строка, или другой список. В частном случае маппинга (описан выше) - мы формируем новый список путем итерирования по оригинальному списку.
Примитивный код такого формирования порой выглядит, хотя и понятно, но неразумно длинно (допустим, для квадратов чисел):
Этот же код можно удобно записать в виде спискового включения (нам не нравится такое название, поэтому здесь и далее я буду называть их "компрехами"):
Можно заметить, что в наших примитивных кодах всё же все не так примитивно. Обычно мы вполняем одновременно и маппинг и фильтрацию внутри цикла for прежде, чем добавить элемент (например, новый список должен содержать квадраты только четных чисел). В этом случае мы пишем что-то вроде:
Но, "компрехи" позволяют делать и это довольно лаконично:
В общем случае, "компрех" описывается таким правилом (справедливо и для генераторов, но о них в других статьях):
Так же в "компрехах" доступны и вложенные циклы. Они записываются слева направо.
Например, для раскрытия двумерного массива (матрицы) в одномерный мы обычно пишем что-то вроде:
на выходе будет одномерный ("планарный") массив [1,2,3,4,5,6,7,8,9,10,11,12]
Тот же код на "компрехах":
Стоит заметить, что условие все равно записывается в конце после всех вложенных циклов for. В условии доступны все итераторы, с которыми в данный момент работают циклы.
Довольно часто мы сталкиваемся с задачей создания списка путем итерирования по чему-либо, будь то строка, или другой список. В частном случае маппинга (описан выше) - мы формируем новый список путем итерирования по оригинальному списку.
Примитивный код такого формирования порой выглядит, хотя и понятно, но неразумно длинно (допустим, для квадратов чисел):
Python:
somelist = [1,2,3,4,5,6,7,8,9]
newlist = []
for i in somelist:
newlist.append(i**2)
Python:
somelist = [1,2,3,4,5,6,7,8,9]
newlist = [i**2 for i in somelist]
Можно заметить, что в наших примитивных кодах всё же все не так примитивно. Обычно мы вполняем одновременно и маппинг и фильтрацию внутри цикла for прежде, чем добавить элемент (например, новый список должен содержать квадраты только четных чисел). В этом случае мы пишем что-то вроде:
Python:
somelist = [1,2,3,4,5,6,7,8,9]
newlist = []
for i in somelist:
if not i%2:
newlist.append(i**2)
Python:
somelist = [1,2,3,4,5,6,7,8,9]
newlist = [i for i in somelist if not i%2]
В общем случае, "компрех" описывается таким правилом (справедливо и для генераторов, но о них в других статьях):
Код:
[новый_элемент for новый_элемент in итерируемое if условие, в котором доступно значение элемента]
Например, для раскрытия двумерного массива (матрицы) в одномерный мы обычно пишем что-то вроде:
Python:
matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
planar = []
for i in matrix:
for j in i:
planar.append(j)
Тот же код на "компрехах":
Python:
matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
planar = [j for i in matrix for j in i]
Стоит заметить, что условие все равно записывается в конце после всех вложенных циклов for. В условии доступны все итераторы, с которыми в данный момент работают циклы.