2012-05-23 3 views
3
input = "foo ,,bar ,baz," 
tags = [x.strip() for x in input.split(',') if len(x.strip()) > 0] 

원하는 출력은 분명히 빈 문자열이없는 목록입니다.이 파이썬 목록 이해력 표현을 단순화 할 수 있습니까?

질문은 마이크로 최적화의 정신에 있습니다. 방법이 있습니까 strip() 후보가 x 두 번 즉, 한 번 테스트 및 추가 한 번?

두 번 작업을 수행하지 않고도 목록에 추가 할 수있는 표현식에서 값을 생성 할 수 있습니까?

+0

를 반환합니다. 스트립()이 그 결과를 캐시한다면, 나는 생각하지 않는다.) 아니면 중간 변수가 필요하다는 것을 알 필요가있다. –

답변

9

새 문자열을 만드는 것은 항상 그것을 스캔하는 것보다 비용이 많이 듭니다. x.isspace() 내가 더 같은데요 ... 첫 번째 공백이 아닌 문자가이 너무 작동

tags = [x.strip() for x in input.split(',') if x and not x.isspace()] 
+0

@Chris,이게 더 나은가요? –

+0

예. 그리고 그것은 내 것보다 더 빠릅니다. (1.95에 비해 1.6 초). –

+0

@gnibbler 감사합니다. 이것은 좋은 근거입니다. – markdsievers

3
text = 'foo ,,bar ,baz,' 

(나는 inputtext보다는 input을 사용하여 내장 명령의 이름입니다. 그림자 내장 명령을 피하십시오.) 모든

먼저, len(x.strip()) > 0x.strip()로 간단하게 작성 (더 효율적으로) 할 수있다. 당신이 정말로 원한다면

tags = [x for x in (x.strip() for x in text.split(',')) if x] 

, 당신도 할 수 : 당신이 정말 당신이 한 번만 스트립을 할 수 싶었지만, 더 빨리 될 거라고 경우 잘 모르겠어요 경우

tags = [x.strip() for x in text.split(',') if x.strip()] 

>>> from timeit import timeit 
>>> timeit(lambda: [x.strip() for x in text.split(',') if x.strip()]) 
1.9443869590759277 
>>> timeit(lambda: [x for x in (x.strip() for x in text.split(',')) if x]) 
2.1135239601135254 
>>> timeit(lambda: filter(bool, map(lambda x: x.strip(), text.split(',')))) 
2.52907395362854 
,691 :

tags = filter(bool, map(lambda x: x.strip(), text.split(','))) 

성능 수치 ... 기능적으로 그것을 할

알다시피, 첫 번째가 가장 빠릅니다.

+0

팁을 주셔서 감사합니다. '우선 ...'이라는 말은 당신이 일하는 것에 대해 두 번 비춰 줄 수 있음을 의미합니까? – markdsievers

+0

@marksievers : 예, 지금 추가했습니다. –

+0

@marksievers : 예, 그렇습니다; 그러나 이것이 매우 유용한 코드 경로이고 마이크로 최적화에 관심이 있다면 @ gnibbler의'if x and not x.isspace()'*는'x.strip()'보다 빠릅니다. –

1

발생 후

text = "foo ,,bar ,baz," 
text.replace(',',' ').split() 
+0

네, 이것이 가장 좋은 방법입니다. – georg

+1

아니요, 모든 경우에 작동하지는 않습니다 (예 : 'text = "foo, bar ,, baz"'. ','를 공백으로 바꾸십시오. 즉,'text.replace (',', '') .split()'이 더 좋습니다. – mhawke

+0

@mhawke : 감사합니다 – ChessMaster

관련 문제