Вопрос по python, list-comprehension – Двойная итерация в понимании списка

167

В Python вы можете иметь несколько итераторов в понимании списка, например

[(x,y) for x in a for y in b]

для некоторых подходящих последовательностей а и б. Мне известно о семантике вложенных циклов в представлениях списков Python.

Мой вопрос: может ли один итератор в понимании ссылаться на другой? Другими словами: Могу ли я иметь что-то вроде этого:

[x for x in a for a in b]

где текущее значение внешнего цикла является итератором внутреннего?

Например, если у меня есть вложенный список:

a=[[1,2],[3,4]]

каким должно быть выражение для понимания списка для достижения этого результата:

[1,2,3,4]

?? (Пожалуйста, перечислите только ответы на осмысление, так как это то, что я хочу выяснить).

Ваш Ответ

8   ответов
3

вы можете использовать точно такую же переменную для члена списка ввода, к которому в данный момент осуществляется доступand для элемента внутри этого члена. Тем не менее, это может даже сделать его более (список) непонятным.

input = [[1, 2], [3, 4]]
[x for x in input for x in x]

Первыйfor x in input оценивается, приводя к одному члену списка ввода, затем Python проходит по второй частиfor x in x в течение которого значение x перезаписывается текущим элементом, к которому он обращается, тогда первыйx определяет, что мы хотим вернуть.

36

Взять, к примеру:[str(x) for i in range(3) for x in foo(i)]

Позвольте ему разложить это:

def foo(i):
    return i, i + 0.5

[str(x)
    for i in range(3)
        for x in foo(i)
]

# is same as
for i in range(3):
    for x in foo(i):
        yield str(x)
Что за откровение !!
Насколько я понимаю, причина этого в том, что "первая из перечисленных итераций является самой верхней итерацией, которая была бы напечатана, если бы понимание было записано как вложенное для циклов". Причина, по которой это противоречит интуиции, заключается в том, что цикл OUTER (самый верхний, если он записан как вложенные циклы for) появляется во ВНУТРИ заключенного в скобки списка / dict (объект понимания и понимания). И наоборот, цикл INNER (самый внутренний, когда он записан как вложенные циклы for) - это как раз крайний правый цикл в понимании, и таким образом он появляется вне Вне понимания.
7

следует вложить скобки массива. см. пример ниже, где каждый добавляется к каждому элементу.

>>> a = [[1, 2], [3, 4]]

>>> [[col +1 for col in row] for row in a]
[[2, 3], [4, 5]]

>>> [col +1 for row in a for col in row]
[2, 3, 4, 5]
17

>>> a = [[1, 2], [3, 4]]
>>> [x for x in b for b in a]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'b' is not defined

>>> [x for b in a for x in b]
[1, 2, 3, 4]
>>> [x for x in b for b in a]
[3, 3, 4, 4]

Я предполагаю, что Python анализирует понимание списка слева направо. Это означает, что первыйfor цикл, который происходит, будет выполнен первым.

Вторая «проблема» это то, чтоb получает "утечка" вне списка понимания. После первого успешного понимания спискаb == [3, 4].

Интересный момент. Я был удивлен этим:x = 'hello'; [x for x in xrange(1,5)]; print x # x is now 4
Эта утечка была исправлена в Python 3:stackoverflow.com/questions/4198906/…
131

>>> [x for b in a for x in b] # Works fine

В то время как вы просили дать ответы на вопросы по списку, позвольте мне также указать на превосходный itertools.chain ():

>>> from itertools import chain
>>> list(chain.from_iterable(a))
>>> list(chain(*a)) # If you're using python < 2.6
96

я не заботился о том, какая петля является внутренней, а какая внешней. Понимание списка должно быть таким:

[x for b in a for x in b]

чтобы получить желаемый результат, и да, одно текущее значение может быть итератором для следующего цикла :-). Извините за шум.

Это выглядит очень чисто, если вы вставляете символы новой строки перед каждым "для".
Синтаксис понимания списка не является одной из самых ярких точек Python.
Еа. Я не уверен, что это "обычный" использовать для понимания списка, но очень прискорбно, что в Python цепочка настолько неприятна.
@Glenn Да, это легко запутать не только в простых выражениях. ThomasH
Вау, это полностью противоположно тому, что имеет смысл в моей голове.
89

a,b,x,y не имеют большого значения для меня! Предположим, у вас есть текст, полный предложений, и вы хотите массив слов.

# Without list comprehension
list_of_words = []
for sentence in text:
    for word in sentence:
       list_of_words.append(word)
return list_of_words

Мне нравится думать о списочном понимании как о растягивании кода по горизонтали.

Попробуйте разбить его на:

# List Comprehension 
[word for sentence in text for word in sentence]
& quot; Есть только две серьезные проблемы в области компьютерных наук: аннулирование кэша и присвоение имен. & quot; - Фил Карлтон
Спасибо, это заставило меня понять вложенные списки-понимания =)
Блестящее объяснение!
2

[row[i] for row in a for i in range(len(a))]

result: [1, 2, 3, 4]

Похожие вопросы