왜 파이썬은리스트를위한 "flatten"함수를 가지고 있지 않습니까?


39

Erlang과 Ruby에는 모두 배열을 평탄화하는 기능이 있습니다. 언어에 추가하는 간단하고 유용한 도구 인 것 같습니다. 하나는 이것을 할 수 있습니다 :

>>> mess = [[1, [2]], 3, [[[4, 5]], 6]]
>>> mess.flatten()
[1, 2, 3, 4, 5, 6]

또는:

>>> import itertools
>>> mess = [[1, [2]], 3, [[[4, 5]], 6]]
>>> list(itertools.flatten(mess))
[1, 2, 3, 4, 5, 6]

대신 파이썬에서는 배열을 처음부터 평평하게하는 함수를 작성하는 데 어려움을 겪어야합니다. 이것은 나에게 어리석은 것처럼 보입니다. 배열을 평평하게하는 것이 일반적입니다. 두 배열을 연결하기 위해 사용자 정의 함수를 작성하는 것과 같습니다.

나는 이것을 결실없이 구글로 만들었으므로 여기에서 묻는다. 십만 개의 다양한 배터리가 포함 된 Python 3과 같은 성숙한 언어가 배열을 평탄화하는 간단한 방법을 제공하지 않는 특별한 이유가 있습니까? 그러한 기능을 포함한다는 아이디어는 어느 시점에서 논의되고 거부 되었습니까?


2
@detly : 여러 쿼리를 사용하여 다른 소스에서 데이터를 검색 할 때 최근에 병합이 누락되었습니다. 각 쿼리는 사전 목록을 반환하므로 결국 사전 목록으로 바뀌는 사전 목록이 있습니다. 나는 루프 +를 사용 extend했지만 평탄화는 훨씬 더 우아했을 것입니다. 그러나이 패턴이 표준 라이브러리에서 평평 해지는 것을 정당화 할만 큼 흔하다면 상처를 입습니다.
조르지오

4
"데이터에 실수로 데이터 구조를 변경하는 버그를 코드에 도입한다고 가정 해 봅시다. flatten은 여전히 ​​작동하지만 완전히 잘못된 결과를 낳습니다." ;-)
조르지오


2
@BryanOakley 이전 의견도 참고하십시오 (다단계 목록
아니지만

3
Mathemaica에 내장되어 있으며 광범위하게 사용합니다.
Per Alexandersson

답변:


34

flatten표준 라이브러리에 추가 될 함수에 대한 제안은 python-devpython-ideas 메일 링리스트 에 수시로 나타납니다 . 파이썬 개발자는 일반적으로 다음과 같은 점으로 응답합니다.

  1. 1 단계 평탄화 (반복 가능 항목의 반복 가능을 단일 반복 가능으로 변환)는 간단한 1 행 표현식 (x for y in z for x in y)이며, 어떤 경우에도 이미 표준 라이브러리에 이름 아래에 itertools.chain.from_iterable있습니다.

  2. 범용 다단계 병합의 사용 사례는 무엇입니까? 이것들이 함수가 표준 라이브러리에 추가되기에 충분히 매력적입니까?

  3. 범용 다단계 병합은 언제 병합하고 언제 떠날지를 결정합니까? "반복 가능한 인터페이스를 지원하는 모든 것을 평평하게하는 것"과 같은 규칙이 작동한다고 생각할 수도 있지만, 무한 루프가 발생할 수 있습니다 flatten('a').

예를 들어 Raymond Hettinger를 참조하십시오 .

comp.lang.python 에서 광고 구역 에 대해 논의되었습니다 . 사람들은 아직 사소한 해결책이없는 합법적 인 사용 사례를 찾는 것보다 자신의 평평한 버전을 쓰는 것을 즐기는 것 같습니다.

범용 플래 튼은 원자가 무엇인지, 더 세분화 될 수있는 방법을 알려줄 수있는 방법이 필요합니다. 또한 노드와 나뭇잎의 데이터 (선주문, 우편 주문, 주문 주문 순회 등)를 사용하여 트리와 같은 데이터 구조의 입력을 처리하도록 알고리즘을 확장해야하는 방법은 명확하지 않습니다.


명백히 말하면, 이것은 1- 레벨 flatten함수가로 정의 될 수 있음을 의미합니다 lambda z: [x for y in z for x in y].
Christopher Martin

1
"일반적인 플래너는 원자가 무엇인지, 더 세분화 될 수있는 방법을 알려줄 방법이 필요합니다.": 이것은 OOP를 사용하여 해결할 수있는 문제인 것 같습니다 flatten. flatten객체가 합성 인 경우, 이 메소드의 구현은 서브 컴포넌트를 재귀 적으로 호출해야합니다 . 불행히도 AFAIK가 모든 값을 파이썬의 객체는 아닙니다. 루비에서는 작동해야합니다.
조르지오

1
지속적인 "for in in"이 아니라 1 단계 flatten을위한 flatten helper는 이미 충분한 IMO 사례입니다. 쉽게 읽을 수
dtc

2
@Giorgio Python은 그러한 방법에서 멀어집니다. 프로토콜이 선호되며, OOP 디자인보다 훨씬 원활하게 작업 할 수 있기 때문에 구현할 필요가 거의 없습니다.
jpmc26

8

그것은 그러한 방법과 함께 제공되지만 그것을 평평하게 부르지는 않습니다. " 체인 "이라고합니다. 반복자를 반환 한 다음 list () 함수를 다시 사용하여 목록으로 다시 설정해야합니다. *를 사용하지 않으려면 두 번째 "from_iterator"버전을 사용할 수 있습니다. Python 3 에서도 동일 하게 작동합니다. 목록 입력이 목록 목록이 아닌 경우 실패합니다.

[[1], [2, 3], [3, 4, 5]] #yes
[1, 2, [5, 6]] #no

compiler.ast 모듈에 flatten 메소드가 한 번에 있었지만 2.6에서 더 이상 사용되지 않고 3.0에서 제거되었습니다. 임의로 중첩 된 목록에 필요한 임의 깊이 재귀는 Python의 보수적 인 최대 재귀 깊이와 잘 작동하지 않습니다. 컴파일러 제거에 대한 추론은 주로 엉망 이기 때문 입니다. 컴파일러는 ast 로 바뀌 었지만 납작하게 남겨졌습니다.

임의의 깊이는 numpy의 배열과 해당 라이브러리의 평탄화로 얻을 수 있습니다.


chain.from_iterator당신이 말했듯이 기능은, 두 차원 목록을 평평하게하는 데 사용할 수 있습니다. actualy 받아 평평 기능, 어떤 중첩 된 목록을 반환 한 차원 목록의 양, 아직 (적어도 내 의견)의 경우 많은에서 대량으로 유용 할 것이다
Hubro

2
@Hubro : "많은 경우"— 이름을 6으로 지정할 수 있습니까?
Gareth Rees

1
@GarethRees : 여기에 몇 가지 예가 있습니다 : programmers.stackexchange.com/questions/254279/…
Hubro

또한 다른 언어가 실제로 매우 간단한 방법으로 목록을 평평하게하는 기능을 제공한다면, 그것은 그 간단한 능력을 파이썬에 추가하는 데 도움이되는 가장 강력한 주장 중 하나라고 주장합니다.
Bobort

반복자 또는 생성기를 반환합니까?
jpmc26

-1

... 어쩌면 스스로 작성하는 것이 어렵지 않기 때문에

def flatten(l): return flatten(l[0]) + (flatten(l[1:]) if len(l) > 1 else []) if type(l) is list else [l]

... 그리고 당신이 원하는 모든 것을 평평하게하십시오 :)

>>> flatten([1,[2,3],4])
[1, 2, 3, 4]
>>> flatten([1, [2, 3], 4, [5, [6, {'name': 'some_name', 'age':30}, 7]], [8, 9, [10, [11, [12, [13, {'some', 'set'}, 14, [15, 'some_string'], 16], 17, 18], 19], 20], 21, 22, [23, 24], 25], 26, 27, 28, 29, 30])
[1, 2, 3, 4, 5, 6, {'age': 30, 'name': 'some_name'}, 7, 8, 9, 10, 11, 12, 13, set(['set', 'some']), 14, 15, 'some_string', 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
>>> 

8
asker는 "Python에서는 배열을 처음부터 평탄화하는 함수를 작성하는 데 어려움을 겪어야한다"고 알고 있습니다. "이것은 어리석은 것처럼 보입니다. 배열을 평탄화하는 것은 일반적인 일입니다. 두 배열을 연결하기 위해 사용자 정의 함수를 작성 해야하는 것과 같습니다."
gnat

1
주제에서 ...하지만 슈퍼 멋진 :-) !!
SeF

이 답변은 OP에게 자신이 함수를 코딩하는 방법을 몰랐기 때문에 좋은 개발자가 아니라고 말하는 것과 같습니다. 주제를 벗어난 경우에도 질문에 걸려 넘어지는 사람들에게 유용한 코드이므로 답변의 시작 부분을 수정하십시오.
Federico Bonelli
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.