2012-07-04 4 views
3

의 목록을 줄일?다음 뭐가 문제 목록

lss = reduce(list.extend, [[1],[2]], []) 

원인 사용 방법 :

Traceback (most recent call last): 
    File "<pyshell#230>", line 1, in <module> 
    lss = reduce(list.extend, [[1],[2]], []) 
TypeError: descriptor 'extend' requires a 'list' object but received a 'NoneType' 

나는 NoneType가 어디에서 오는 모르겠어요.

+0

원하는 결과가 무엇인가/무엇 목록이 확장하려고 : 동등? –

답변

13

대신을 시도

lss = reduce(lambda acc, ele : acc + ele, [[1],[2]], []) 

lss 
> [1, 2] 

문제는 그 extend() 반환 None을합니다 (NoneType은 어디에서 오는 그건), 그리고 당신이 무엇을 원하는 작동하지 않습니다 - reduce()에 전달하는 기능 값을 반환해야합니다. 누적 결과는 지금까지입니다.

+0

나는 내가 그 일을 할 수 있음을 깨닫는다. 나는 여전히 list.extend 메소드를 사용하여 무엇이 잘못되었는지 알고 싶다. 그것은 그것이 작동 해야하는 것 같습니다. - 귀하의 편집 내용이 이에 응답했습니다. – cammil

+1

위에서 언급 한 @cammil :'extend()'는 항상 _ Noneways를 리턴합니다; 'reduce()'가 실행 된 함수를 작동 시키려면 _has to_ value를 반환한다 : 지금까지의 누적 결과. –

+2

파이썬에서 Command/Query Separation을 준수하고 있기 때문에 파이썬에서 데이터 구조를 변경하는 함수는 항상'None'을 반환하기 때문에 * 왜 *'list.extend()'가'None'을 리턴하는지 궁금해하는 사람이 있습니다. http://en.wikipedia.org/wiki/Command-query_separation – steveha

5

나는 그것이 가치가 있다고 지적 생각 :

sum([[1],[2]], []) 

도 작동합니까, 나는 빨리 줄이기 위해 람다를 통과 한 후가 될 것입니다 확신합니다.

나는 다른 방법의 속도 궁금했다, 그래서 나는 몇 가지 테스트를했다 :

reduce(lambda a,b:a+b, x, [])    3644.38161492 
reduce(list.__add__, x, [])     3609.44079709 
sum(x,[])         3526.84987307 
y = [];for z in x: y.extend(z)    143.370306969 
y = [];map(y.extend,x)      71.7020270824 
y = [None]*400;del y[:];map(y.extend,x)  66.2245891094 
list(itertools.chain(*x))     102.285979986 
list(itertools.chain.from_iterable(x))  96.6231369972 
[a for b in x for a in b]     203.764872074 

그리고 PyPy에

(때문에 왜 안)

reduce(lambda a,b:a+b, x, [])    4797.5895648 
reduce(list.__add__, x, [])     4794.01214004 
sum(x,[])         4748.02929902 
y = [];for z in x: y.extend(z)    56.9253079891 
y = [];map(y.extend,x)      73.8642170429 
y = [None]*400;del y[:];map(y.extend,x)  152.157783031 
list(itertools.chain(*x))     633.854824066 
list(itertools.chain.from_iterable(x))  629.917827129 
[a for b in x for a in b]      89.6922459602 

x = [[1,2,3,4],[2,3,4,5],[3,4,5,6],[4,5,6,7],[5,6,7,8],[6,7,8,9],[7,8,9,10],[8,9,10,11]]*100 

결론 :

  1. 줄이기에 람다 사용 속도가 느림
  2. sum 기능이 빠르면 줄입니다.
  3. 목록을 추가하는 속도가 느립니다.
  4. 파이썬 루프 오버 헤드가 중요합니다.
  5. 오스카르 로페즈 바와 같이
+0

x = x * 100으로 설정하면 알고리즘 간의 실제 속도 차이를 볼 수 있습니다. – DSM

+0

@DSM, 맞습니다. 그래서 그렇게했습니다. –

+0

+1 흥미로운 타이밍 – jamylak

1

list.extend 복귀 Nonereduce 따라서는 사용할 수 없습니다. 대안 lambda 기능의 제안 된 사용에, 당신은 또한 reduce으로 list.__add__을 사용할 수

>>> reduce(list.__add__, [[1],[2]], []) 
[1, 2] 
1

당신은 까지 최초의 반복자의 요소를 반환하는 반복자를 확인 itertools.chain

을 사용할 수 있습니다 그것은 소진되면, 다음 반복 가능으로 진행하여 모든 반복 횟수가 모두 소모됩니다. 연속 시퀀스를 단일 시퀀스로 처리하는 데 사용됩니다. ?

def chain(*iterables): 
    # chain('ABC', 'DEF') --> A B C D E F 
    for it in iterables: 
     for element in it: 
      yield element 
관련 문제