#python #list #iterator #list-comprehension
#python #Список #итератор #понимание списка
Вопрос:
Я хочу объединить два или более разных итератора в понимании списка.
Предположим, я хочу объединить прописные и строчные буквы в список. Первоначальный способ, которым я думал, был таким,
lst1 = [chr(i) for i in range(97,123)]
lst2 = [chr(i) for i in range(65,91)]
lst = lst1 lst2
Однако я подумал, что должны быть какие-то другие способы сделать это красиво в одной строке, а затем я использовал это с модулем itertools,
lst = [chr(i) for i in itertools.chain(range(97,123), range(65,91))]
В конце я также подумал о распаковке кортежей,
lst = [chr(i) for i in (*range(97,123), *range(65,91))]
Itertools был медленнее по сравнению с двумя другими методами (распаковка кортежей была самой быстрой)
Например, символы в первом и втором диапазонах составляют список
>>> lst1
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
>>> lst2
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
Я хочу, чтобы они были объединены только с 1 итератором, а не с двумя отдельными. Ниже приведен пример объединенного списка, в котором используются 2 разных диапазона значений,
>>> lst
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
Есть ли какой-либо способ улучшить это или изменить дизайн?
Комментарии:
1. Вы пробовали
itertools.chain
оба генератора вместо диапазонов?list(itertools.chain((chr(i) for i in range(97, 123)), (chr(i) for i in range(65, 91))))
2. Не могли бы вы предоставить пример вывода, чтобы мы могли точно видеть, какое решение вы ищете?
Ответ №1:
Вы нашли правильное решение (решения).
Примечание: itertools.chain
может быть тривиально медленнее, но его преимущество в том, что он (фактически) не требует затрат памяти, и я бы рекомендовал его в целом. range
уже (фактически) нулевая нагрузка на память, поэтому использование его с chain
означает отсутствие каких-либо значимых затрат памяти вообще, в то время как использование распаковки в a tuple
предполагает реализацию обоих range
s как a tuple
без реальной причины. Если размеры никогда не увеличиваются, то что угодно, но если входные данные могут быть переменной длины, chain
безопаснее, чем реализация неограниченной итерации в памяти.
Конечно, для вашего конкретного случая очевидным решением (которое значительно более читабельно) является:
import string
lst = list(string.ascii_letters)
Комментарии:
1. 1 для альтернативного способа, который обеспечивает тот же порядок букв (заглавные буквы сохраняются, несмотря на меньшее числовое значение). Я полностью ожидал
list(string.ascii_letters)
, что меня будут заказывать противоположным образом.2. @Adirio: На самом деле я тоже; первоначально я написал это как конкатенацию
string.ascii_lowercase
иstring.ascii_uppercase
, затем понял, чтоascii_letters
это уже в правильном порядке. 🙂
Ответ №2:
Это, вероятно, не так аккуратно, как список, извлеченный из пакета string
, НО он решает ваш вопрос, создавая единую итерацию путем объединения двух наборов, и также должен быть достаточно эффективным.
>>> [chr(i) for i in set(range(97,123)).union(range(65,91))]
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
Комментарии:
1. Три замечания: 1. Полагаться на
set
s для сохранения порядка — ужасная идея (и, как это бывает, это приводит к неправильному порядку, вводя сначала прописные буквы, хотя несколько удивительно, что все буквы в остальном в порядке). 2. Вам не нужно преобразовывать аргумент вunion
в aset
; он принимает произвольные итерации (если бы вы использовали|
для объединения, вам нужно, чтобы оба былиset
s , но именованные методы не являются конкретными). 3. Здесь нет никакой существенной выгоды от использованияset
s по сравнению с простым объединениемrange
s; распаковка двухrange
s в atuple
быстрее для получения одной коллекции.2. Привет, спасибо за просвещение! Многому научился: D