programing

목록 이해에서의 이중 반복

copyandpastes 2022. 10. 1. 22:15
반응형

목록 이해에서의 이중 반복

Python에서는 목록 이해에 여러 개의 반복기를 가질 수 있습니다.

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

적절한 시퀀스 a와 b에 대해 설명합니다.Python의 리스트 컴프리션의 네스트 루프 의미에 대해 알고 있습니다.

질문입니다. 이해의 한 반복자가 다른 반복자를 참조할 수 있습니까?즉, 다음과 같은 것을 얻을 수 있을까요?

[x for x in a for a in b]

여기서 외부 루프의 전류 값은 내부 루프의 반복기입니까?

예를 들어, 중첩된 목록이 있는 경우:

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

이 결과를 얻기 위해 리스트 이해 표현은 무엇일까?

[1,2,3,4]

? (이것이 제가 알고 싶은 것이므로 이해력만 기재해 주십시오.)

텍스트가 문장으로 가득 차 있고 단어 배열이 필요하다고 가정해 보십시오.

# 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]

예:

>>> text = (("Hi", "Steve!"), ("What's", "up?"))
>>> [word for sentence in text for word in sentence]
['Hi', 'Steve!', "What's", 'up?']

이것은 발전기에도 유효합니다.

>>> text = (("Hi", "Steve!"), ("What's", "up?"))
>>> gen = (word for sentence in text for word in sentence)
>>> for word in gen: print(word)
Hi
Steve!
What's
up?

자신의 제안으로 질문에 답하려면:

>>> [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

오, 내가 앤서를 찾은 것 같아.나는 어떤 루프가 내부이고 어떤 루프가 외부인지에 대해 충분히 신경 쓰지 않았다.목록 이해는 다음과 같아야 합니다.

[x for b in a for x in b]

원하는 결과를 얻을 수 있습니다.그렇습니다.다음 루프의 반복이 되는 것은 1개의 현재 값입니다.

반복자의 순서가 직관에 반하는 것처럼 보일 수 있습니다.

를 들면, '보다 낫다' 입니다.[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)

ThomasH는 이미 좋은 답변을 추가했지만, 어떤 일이 일어나는지 보여드리고 싶습니다.

>>> 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은 리스트의 이해를 왼쪽에서 오른쪽으로 해석하는 것 같습니다., 첫 ,, 첫, 째, 째, 째, 째, this,for루프가 먼저 실행됩니다.

번째 '는 '문제'입니다.b리스트의 이해에서 「불필요」를 제외합니다. 성공 후b == [3, 4].

이 메모리 기술은 많은 도움이 됩니다.

[ <RETURNED_VALUE> <OUTER_LOOP1> <INNER_LOOP2> <INNER_LOOP3> ... <OPTIONAL_IF> ]

이제 Return + Outer-loop을 유일한 올바른 순서라고 생각할 수 있습니다.

상기의 것을 알고 있기 때문에, 3개의 루프에 대해서도 리스트의 포괄적인 순서는 간단하다고 생각됩니다.


c=[111, 222, 333]
b=[11, 22, 33]
a=[1, 2, 3]

print(
  [
    (i, j, k)                            # <RETURNED_VALUE> 
    for i in a for j in b for k in c     # in order: loop1, loop2, loop3
    if i < 2 and j < 20 and k < 200      # <OPTIONAL_IF>
  ]
)
[(1, 11, 111)]

위의 내용은 단지 다음과 같습니다.

for i in a:                         # outer loop1 GOES SECOND
  for j in b:                       # inner loop2 GOES THIRD
    for k in c:                     # inner loop3 GOES FOURTH
      if i < 2 and j < 20 and k < 200:
        print((i, j, k))            # returned value GOES FIRST

의 네스트 리스트를 , '네스트 리스트/리스트'의 경우입니다.a★★★★★★★★★★★★★★★★★★:

a = [[1,2],[3,4]]
[i2    for i1 in a      for i2 in i1]
which return [1, 2, 3, 4]

다른 중첩 수준에 대해

a = [[[1, 2], [3, 4]], [[5, 6], [7, 8, 9]], [[10]]]
[i3    for i1 in a      for i2 in i1     for i3 in i2]
which return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

등등

다차원 어레이를 유지하려면 어레이 브래킷을 중첩해야 합니다.각 요소에 하나씩 추가되는 다음 예를 참조하십시오.

>>> 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]

나는 첫 번째 시도에서 절대 이중 목록 이해를 쓸 수 없었다.PEP202를 읽어보면 그 이유는 영어로 읽는 것과 반대로 구현되어 있기 때문입니다.좋은 소식은 이것이 논리적으로 타당한 구현이기 때문에 일단 구조를 이해하면 매우 쉽게 올바르게 구현될 수 있다는 것입니다.

a, b, c, d를 연속해서 중첩된 객체로 합니다.저에게는 목록 이해 범위를 넓히는 직관적인 방법이 영어를 흉내 낼 수 있습니다.

# works
[f(b) for b in a]
# does not work
[f(c) for c in b for b in a]
[f(c) for c in g(b) for b in a]
[f(d) for d in c for c in b for b in a]

즉, 아래에서 위로 읽게 됩니다.

# wrong logic
(((d for d in c) for c in b) for b in a)

그러나 Python은 네스트된 목록을 구현하지 않습니다.대신 구현에서는 첫 번째 청크가 완전히 분리된 것으로 간주되고 다음으로 이 청크를 체인으로 합니다.forin즉, 위에서 아래로(아래쪽으로) 단일 블록에 있습니다.

# right logic
d: (for b in a, for c in b, for d in c)

가장 깊은 중첩 레벨(for d in c)는 목록의 마지막 개체에서 가장 멀리 떨어져 있습니다.d그 이유는 Guido 자신으로부터 나온 입니다.

[... for x... for y...]루프를 위해 중첩된 것처럼 마지막 인덱스가 가장 빠르게 변화합니다.

Skam의 텍스트 예제를 사용하면 더 명확해집니다.

# word: for sentence in text, for word in sentence
[word for sentence in text for word in sentence]

# letter: for sentence in text, for word in sentence, for letter in word
[letter for sentence in text for word in sentence for letter in word]

# letter:
#     for sentence in text if len(sentence) > 2, 
#     for word in sentence[0], 
#     for letter in word if letter.isvowel()
[letter for sentence in text if len(sentence) > 2 for word in sentence[0] for letter in word if letter.isvowel()]

이게 더 이해하기 쉽다고 느껴요.

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

result: [1, 2, 3, 4]

또, 현재 액세스 되고 있는 입력 리스트의 멤버와 이 멤버내의 요소에 대해서, 같은 변수만을 사용할 수 있습니다.그러나 이것은 그것을 더 이해할 수 없게 할 수도 있다.

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

첫번째for x in input평가되어 입력의 1개의 멤버 리스트로 이어지며, Python은 두 번째 파트를 통과합니다.for x in xx 값이 액세스 중인 현재 요소에 의해 덮어쓰기되는 동안 첫 번째 값x반환하고 싶은 것을 정의합니다.

이 platen_nlevel 함수는 중첩된 list1을 재귀적으로 호출하여 한 레벨로 변환합니다.이것을 시험해 보세요.

def flatten_nlevel(list1, flat_list):
    for sublist in list1:
        if isinstance(sublist, type(list)):        
            flatten_nlevel(sublist, flat_list)
        else:
            flat_list.append(sublist)

list1 = [1,[1,[2,3,[4,6]],4],5]

items = []
flatten_nlevel(list1,items)
print(items)

출력:

[1, 1, 2, 3, 4, 6, 4, 5]

언급URL : https://stackoverflow.com/questions/1198777/double-iteration-in-list-comprehension

반응형