중첩 된 목록에 대한 목록 이해?


219

이 중첩 목록이 있습니다.

l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']]

이제하고 싶은 것은 목록의 각 요소를 부동으로 변환하는 것입니다. 내 해결책은 이것입니다 :

newList = []
for x in l:
  for y in x:
    newList.append(float(y))

그러나 이것은 중첩 된 목록 이해를 사용하여 수행 할 수 있습니까?

내가 한 일은 :

[float(y) for y in x for x in l]

그러나 결과는 2400의 합계로 100의 무리입니다.

어떤 해결책이든, 설명은 대단히 감사하겠습니다. 감사!


15
당신은 마십시오 또한 목록을 평평하게하고 싶어?
Greg Hewgill

@GregHewgill : OP는 응답하지 않았지만 수락 한 답변에 따라 중첩을 그대로 유지하고 싶었습니다.
smci

답변:


318

중첩 된 목록 이해로이를 수행하는 방법은 다음과 같습니다.

[[float(y) for y in x] for x in l]

이렇게하면 문자열 대신 부동 소수점을 제외하고 시작한 것과 비슷한 목록 목록이 제공됩니다. 하나의 플랫 목록을 원하면을 사용 [float(y) for x in l for y in x]합니다.


191

다음은 중첩 for 루프를 중첩 목록 이해로 변환하는 방법입니다.

여기에 이미지 설명을 입력하십시오

중첩 된 목록 이해는 다음과 같습니다.

            l a b c d e f
                  
In [1]: l = [ [ [ [ [ [ 1 ] ] ] ] ] ]
In [2]: for a in l:
   ...:     for b in a:
   ...:         for c in b:
   ...:             for d in c:
   ...:                 for e in d:
   ...:                     for f in e:
   ...:                         print(float(f))
   ...:                         
1.0

In [3]: [float(f)
         for a in l
   ...:     for b in a
   ...:         for c in b
   ...:             for d in c
   ...:                 for e in d
   ...:                     for f in e]
Out[3]: [1.0]

귀하의 경우에는 다음과 같습니다.

In [4]: new_list = [float(y) for x in l for y in x]

21
매우 유용합니다! 생성기에서 루프 (위에서 아래로)가 왼쪽에서 오른쪽으로 정렬되어 있는지 확인합니다. (f(x) for x in l)for 루프의 두 번째 줄이 왼쪽에 있기 때문에 이것은 분명하지 않습니다 .
user48956

이것은 실제로 나와 함께 집에 타격을주는 하나의 설명 인 것 같습니다, 감사합니다!
Douglas Plumley

48
>>> l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']]
>>> new_list = [float(x) for xs in l for x in xs]
>>> new_list
[40.0, 20.0, 10.0, 30.0, 20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0, 30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0]

42

원하는 출력이 무엇인지 모르지만 목록 이해를 사용하는 경우 순서는 중첩 루프의 순서를 따릅니다. 그래서 나는 당신이 원하는 것을 얻었습니다.

[float(y) for x in l for y in x]

원칙은 : 중첩 된 for 루프로 작성할 때와 같은 순서를 사용하는 것입니다.


이 대답해야 몇 번으로 우리는 대괄호로 iteratool 싶지 않아
zinking

1
이것은 중첩되지 않은 목록을 출력하기 때문에 정답이 아닐 수도 있지만, 내가 특히 찾고 있는 원칙 입니다. 감사!
로드리고 E. 프린시 페

4

여기에 조금 늦었지만 실제로 목록 이해가 특히 중첩 된 목록 이해가 어떻게 작동하는지 공유하고 싶었습니다.

New_list= [[float(y) for x in l]

실제로는 다음과 같습니다.

New_list=[]
for x in l:
    New_list.append(x)

그리고 이제 중첩 된 목록 이해 :

[[float(y) for y in x] for x in l]

와 동일;

new_list=[]
for x in l:
    sub_list=[]
    for y in x:
        sub_list.append(float(y))

    new_list.append(sub_list)

print(new_list)

산출:

[[40.0, 20.0, 10.0, 30.0], [20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0], [30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0], [100.0, 100.0], [100.0, 100.0, 100.0, 100.0, 100.0], [100.0, 100.0, 100.0, 100.0]]

3

중첩 된 목록 이해가 마음에 들지 않으면 지도 기능도 사용할 수 있습니다.

>>> from pprint import pprint

>>> l = l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']] 

>>> pprint(l)
[['40', '20', '10', '30'],
['20', '20', '20', '20', '20', '30', '20'],
['30', '20', '30', '50', '10', '30', '20', '20', '20'],
['100', '100'],
['100', '100', '100', '100', '100'],
['100', '100', '100', '100']]

>>> float_l = [map(float, nested_list) for nested_list in l]

>>> pprint(float_l)
[[40.0, 20.0, 10.0, 30.0],
[20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0],
[30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0],
[100.0, 100.0],
[100.0, 100.0, 100.0, 100.0, 100.0],
[100.0, 100.0, 100.0, 100.0]]

코드는 목록 대신 맵 객체를 생성 >>> float_l = [map(float, nested_list) for nested_list in l] [[<map at 0x47be9b0>], [<map at 0x47be2e8>], [<map at 0x47be4a8>], [<map at 0x47beeb8>], [<map at 0x484b048>], [<map at 0x484b0b8>]] 하지만 목록에 추가 호출을 추가하면 예상대로 작동합니다. >>> float_l = [list(map(float, nested_list)) for nested_list in l]
pixelperfect

@pixelperfect는 ( 잘못 알려진 ..) 변경 으로 인해 python3제너레이터를 이해력에서 벗어나게합니다.
javadba

3

비슷한 문제가 있어서이 질문을 보았습니다. Andrew Clark와 narayan의 답변을 공유하고 싶은 성능을 비교했습니다.

두 답변의 주요 차이점은 내부 목록을 반복하는 방법입니다. 그중 하나는 내장 map을 사용 하고 다른 하나는 목록 이해를 사용합니다. 람다 사용이 필요하지 않은 경우 Map 함수는 동등한 목록 이해에 비해 약간의 성능 이점이 있습니다 . 따라서이 질문의 맥락에서map 목록 이해력보다 약간 더 나은 성능을 발휘해야합니다.

성능 벤치 마크를 통해 실제로 적용되는지 확인할 수 있습니다. 파이썬 버전 3.5.0을 사용하여 이러한 모든 테스트를 수행했습니다. 첫 번째 테스트 세트에서 목록 당 요소를 10 으로 유지 하고 목록 수를 10-100,000으로 변경하고 싶습니다.

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*10]"
>>> 100000 loops, best of 3: 15.2 usec per loop   
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*10]"
>>> 10000 loops, best of 3: 19.6 usec per loop 

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*100]"
>>> 100000 loops, best of 3: 15.2 usec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*100]"
>>> 10000 loops, best of 3: 19.6 usec per loop 

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*1000]"
>>> 1000 loops, best of 3: 1.43 msec per loop   
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*1000]"
>>> 100 loops, best of 3: 1.91 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*10000]"
>>> 100 loops, best of 3: 13.6 msec per loop   
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*10000]"
>>> 10 loops, best of 3: 19.1 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*100000]"
>>> 10 loops, best of 3: 164 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*100000]"
>>> 10 loops, best of 3: 216 msec per loop

여기에 이미지 설명을 입력하십시오

다음 테스트 세트에서 목록 당 요소 수를 100 으로 늘리고 싶습니다 .

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*10]"
>>> 10000 loops, best of 3: 110 usec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*10]"
>>> 10000 loops, best of 3: 151 usec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*100]"
>>> 1000 loops, best of 3: 1.11 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*100]"
>>> 1000 loops, best of 3: 1.5 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*1000]"
>>> 100 loops, best of 3: 11.2 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*1000]"
>>> 100 loops, best of 3: 16.7 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*10000]"
>>> 10 loops, best of 3: 134 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*10000]"
>>> 10 loops, best of 3: 171 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*100000]"
>>> 10 loops, best of 3: 1.32 sec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*100000]"
>>> 10 loops, best of 3: 1.7 sec per loop

여기에 이미지 설명을 입력하십시오

용감한 발걸음을 내딛고 목록의 요소 수를 1000으로 수정합니다.

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*10]"
>>> 1000 loops, best of 3: 800 usec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*10]"
>>> 1000 loops, best of 3: 1.16 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*100]"
>>> 100 loops, best of 3: 8.26 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*100]"
>>> 100 loops, best of 3: 11.7 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*1000]"
>>> 10 loops, best of 3: 83.8 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*1000]"
>>> 10 loops, best of 3: 118 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*10000]"
>>> 10 loops, best of 3: 868 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*10000]"
>>> 10 loops, best of 3: 1.23 sec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*100000]"
>>> 10 loops, best of 3: 9.2 sec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*100000]"
>>> 10 loops, best of 3: 12.7 sec per loop

여기에 이미지 설명을 입력하십시오

이 테스트 map에서이 경우 목록 이해에 비해 성능 이점이 있다고 결론을 내릴 수 있습니다 . int또는 로 캐스트하려는 경우에도 적용됩니다 str. 목록 당 요소 수가 적은 적은 수의 목록의 경우 그 차이는 무시할 수 있습니다. 목록 당 더 많은 요소가있는 더 큰 목록 map의 경우 목록 이해 대신 사용하고 싶을 수도 있지만 이는 응용 프로그램 요구에 따라 달라집니다.

그러나 개인적으로 나는 목록 이해가보다 읽기 쉽고 관용적이라고 생각 map합니다. 파이썬에서 사실상의 표준입니다. 일반적으로 사람들은 목록 이해력보다보다 능숙하고 편안합니다 (특히 초보자) map.


2

예, 그러한 코드로 할 수 있습니다 :

l = [[float(y) for y in x] for x in l]

[float(y) for y in x for x in l]이것은 2400의 합계와 함께 100의 무리를 초래할 것입니다.
Boy Pasmo

2

이 문제는 for 루프를 사용하지 않고 해결할 수 있습니다. 단일 라인 코드로 충분합니다. 람다 함수와 함께 중첩 맵을 사용하면 여기에서도 작동합니다.

l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']]

map(lambda x:map(lambda y:float(y),x),l)

그리고 출력 목록은 다음과 같습니다.

[[40.0, 20.0, 10.0, 30.0], [20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0], [30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0], [100.0, 100.0], [100.0, 100.0, 100.0, 100.0, 100.0], [100.0, 100.0, 100.0, 100.0]]

1
람다는 @Andrew Clark 또는 Harry Binswanger의 솔루션 (더 많은 바닐라 목록 이해)에 비해 성능상의 이점이 있습니까? 람다는 읽기가 더 어려워 보입니다.
StefanJCollier

0

내 의견으로는 이것을 수행하는 가장 좋은 방법은 파이썬 itertools패키지 를 사용하는 것 입니다.

>>>import itertools
>>>l1 = [1,2,3]
>>>l2 = [10,20,30]
>>>[l*2 for l in itertools.chain(*[l1,l2])]
[2, 4, 6, 20, 40, 60]


-2
    deck = [] 
    for rank in ranks:
        for suit in suits:
            deck.append(('%s%s')%(rank, suit))

이것은 목록 이해를 사용하여 달성 할 수 있습니다.

[deck.append((rank,suit)) for suit in suits for rank in ranks ]

1
이것은 질문을 전혀 다루지 않는 것으로 보입니다. 답변으로 게시 된 모든 내용은 게시 된 질문에 대한 답변을 시도해야합니다.
Baum mit Augen

이 코드 스 니펫은 문제를 해결할 수 있지만 설명을 포함하면 게시물의 품질을 향상시키는 데 실제로 도움이됩니다. 앞으로 독자에게 질문에 대한 답변을 제공하고 있으며 해당 사람들이 귀하의 코드 제안 이유를 모를 수도 있습니다. 설명 주석으로 코드를 복잡하게 만들지 마십시오. 이렇게하면 코드와 설명의 가독성이 떨어집니다!
Filnor

리스트 이해를 사용하여 루프를 위해 중첩 됨
ADITYA KUMAR

1
자, 이것은 분명히 질문에 대답하려는 시도입니다. 그러나 이것은 OP와 완전히 다른 시나리오 인 것처럼 보이며 중첩 목록을 입력으로 처리하지 않으며 제안이 OP가 이미 시도한 것과 거의 비슷하다는 제안을 변경하더라도 마찬가지입니다. 또한 문자열을 부동으로 변환하는 것에 대한 질문이있을 때 카드에 대한 예가 어떻게 도움이되는지 알지 못합니다.
Baum mit Augen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.