파이썬 목록 이해력; 목록 목록 압축?
여러분. 나는 문제에 대한 가장 우아한 해결책을 찾으려고 노력하고 있는데 파이썬에 내가하려는 일에 내장 된 것이 있는지 궁금했다.
내가하는 일은 이것입니다. 목록 이 있고 항목을 가져와 목록을 반환하는 A
함수 f
가 있습니다. 목록 이해력을 사용하여 모든 것을 A
이렇게 변환 할 수 있습니다 .
[f(a) for a in A]
그러나 이것은 목록 목록을 반환합니다.
[a1,a2,a3] => [[b11,b12],[b21,b22],[b31,b32]]
내가 정말로 원하는 것은 평평한 목록을 얻는 것입니다.
[b11,b12,b21,b22,b31,b32]
이제 다른 언어에도 있습니다. 전통적 flatmap
으로 함수형 프로그래밍 언어로 호출되었으며 .Net은이를 SelectMany
. 파이썬에는 비슷한 것이 있습니까? 목록에 함수를 매핑하고 결과를 평면화하는 깔끔한 방법이 있습니까?
제가 해결하려는 실제 문제는 이것입니다. 디렉토리 목록으로 시작하여 모든 하위 디렉토리를 찾습니다. 그래서;
import os
dirs = ["c:\\usr", "c:\\temp"]
subs = [os.listdir(d) for d in dirs]
print subs
currentliy는 나에게 목록 목록을 제공하지만 정말 목록을 원합니다.
단일 목록 이해에서 중첩 된 반복을 가질 수 있습니다.
[filename for path in dirs for filename in os.listdir(path)]
>>> listOfLists = [[1, 2],[3, 4, 5], [6]]
>>> reduce(list.__add__, listOfLists)
[1, 2, 3, 4, 5, 6]
itertools 솔루션이 이것보다 더 효율적이라고 생각하지만 이것은 매우 비단뱀 적이며 단일 목록 작업을 위해 라이브러리를 가져올 필요가 없습니다.
itertools의 레시피 에서 좋은 답을 찾을 수 있습니다 .
def flatten(listOfLists):
return list(chain.from_iterable(listOfLists))
(참고 : Python 2.6 이상 필요)
제안 된 질문 flatmap
. 일부 구현이 제안되었지만 중간 목록을 불필요하게 만들 수 있습니다. 다음은 반복자를 기반으로 한 구현입니다.
def flatmap(func, *iterable):
return itertools.chain.from_iterable(map(func, *iterable))
In [148]: list(flatmap(os.listdir, ['c:/mfg','c:/Intel']))
Out[148]: ['SPEC.pdf', 'W7ADD64EN006.cdr', 'W7ADD64EN006.pdf', 'ExtremeGraphics', 'Logs']
파이썬 2.X에서 사용하는 itertools.map
대신에 map
.
간단하게 할 수 있습니다.
subs = []
for d in dirs:
subs.extend(os.listdir(d))
일반 더하기 연산자를 사용하여 목록을 연결할 수 있습니다.
>>> [1, 2] + [3, 4]
[1, 2, 3, 4]
내장 함수 sum
는 시퀀스에 숫자를 추가하고 선택적으로 특정 값에서 시작할 수 있습니다.
>>> sum(xrange(10), 100)
145
위의 내용을 결합하여 목록 목록을 병합합니다.
>>> sum([[1, 2], [3, 4]], [])
[1, 2, 3, 4]
이제 다음을 정의 할 수 있습니다 flatmap
.
>>> def flatmap(f, seq):
... return sum([f(s) for s in seq], [])
...
>>> flatmap(range, [1,2,3])
[0, 0, 1, 0, 1, 2]
편집 : 방금 다른 답변 에 대한 주석에서 비판을 보았고 Python 이이 솔루션으로 많은 작은 목록을 불필요하게 작성하고 가비지 수집하는 것이 옳다고 생각합니다. 그래서 그것에 대해 말할 수있는 가장 좋은 것은 함수형 프로그래밍에 익숙하다면 매우 간단하고 간결하다는 것입니다 :-)
import itertools
x=[['b11','b12'],['b21','b22'],['b31']]
y=list(itertools.chain(*x))
print y
itertools는 python2.3 이상에서 작동합니다.
subs = []
map(subs.extend, (os.listdir(d) for d in dirs))
(그러나 Ants의 대답은 더 낫습니다. +1)
다음 itertools.chain()
과 같이 시도해 볼 수 있습니다 .
import itertools
import os
dirs = ["c:\\usr", "c:\\temp"]
subs = list(itertools.chain(*[os.listdir(d) for d in dirs]))
print subs
itertools.chain()
반복자를 반환하므로 list()
.
Google brought me next solution:
def flatten(l):
if isinstance(l,list):
return sum(map(flatten,l))
else:
return l
You can use pyxtension:
from pyxtension.streams import stream
stream([ [1,2,3], [4,5], [], [6] ]).flatMap() == range(7)
def flat_list(arr):
send_back = []
for i in arr:
if type(i) == list:
send_back += flat_list(i)
else:
send_back.append(i)
return send_back
If listA=[list1,list2,list3]
flattened_list=reduce(lambda x,y:x+y,listA)
This will do.
참고URL : https://stackoverflow.com/questions/1077015/python-list-comprehensions-compressing-a-list-of-lists
'Program Tip' 카테고리의 다른 글
Windows가 로컬 컴퓨터에서 Apache2를 시작할 수 없음-문제 (0) | 2020.11.12 |
---|---|
비하인드 뷰 클릭 이벤트 프레임 레이아웃을 비활성화하는 방법 (0) | 2020.11.12 |
UIScrollView가 iOS 6 및 iOS 7에서 맨 위에서 공간을 벗어나는 이유 (0) | 2020.11.12 |
이메일 서버없이 이메일 보내기 테스트 (0) | 2020.11.12 |
"표준 경로"란 무엇입니까? (0) | 2020.11.11 |