2016-06-21 4 views
0

operator.attrgetteritertool.groupby을 사용하여 텍스트 문자열을 공백으로 분리하여 텍스트 사이의 공백을 유지합니다. 이것은 예상 된 동작입니다 :부정 연산자`.airrgetter`

result = process('Am     G   C') 
assert result == [(2, 'Am'), (20, ' '), (1, 'G'), (10, ' '), (1, 'C')] 

나는 내가 람다를 사용하는 것보다 더 파이썬 찾을 수 있기 때문에 attrgetter을 사용하고 싶습니다 말했듯이. 내가 할 수있는 :

text = '''Am     G   C''' 
processed=((k, list(l))for k, l in groupby(text, attrgetter("isspace"))) 
result = [(len(l), "".join(l)) if k else (len(l), " ") for k, l in processed] 

하지만이 반환됩니다

는 정반대 내가 생각해야 할 것입니다
[(1, 'A'), (1, 'm'), (20, '     '), (1, 'G'), (10, '   '), (1, 'C')] 

나는 시도 :

from operator import neg, attrgetter 
text = '''Am     G   C''' 
processed = ((k,list(l)) for k,l in groupby(text, neg(attrgetter("isspace")))) 
result = [(len(l), "".join(l)) if k else (len(l), " ") for k, l in processed] 

을이 예외 :

TypeError: bad operand type for unary -: 'operator.attrgetter'

0에서 반환 된 값을 어떻게 무효화 할 수 있습니까? 키 기능을위한?

+2

그냥 반전하고 사용하는 자신의 함수를 작성하십시오. – jonrsharpe

+1

나는 람다에 의지하지 않고 얻을 수있는 가장 가까운 것이'' ".__ ne__'라고 생각합니다. –

+0

이 특정 질문에서, 당신은 실제로 여기서 함수를 무효화 할 필요가 없습니다. 단지 if/else 표현식의 조건을 무효로하십시오. 그래서'x if y else z'는'x가 아닌 경우 x '가됩니다. 예. k가 아닌 다른 경우 (len (l), ""), 처리 된 k]의 결과는 [result = [(len (l) 'attrgetter ("isspace")'에'str.isspace'를 사용할 수도 있습니다. – Dunes

답변

4

operator.attrgetter은 여기에서 핵심 기능으로 직접 작동하지 않습니다. 대신 str.isspace을 사용할 수

>>> attrgetter("isspace")(" ") 
<built-in method isspace of str object at 0x7f30c4301ab0> 
>>> attrgetter("isspace")(" ")() 
True 

을 :

>>> processed = ((k, list(l)) for k, l in groupby(text, str.isspace)) 
>>> result = [(len(l), " ") if k else (len(l), "".join(l)) for k, l in processed] 
>>> result 
[(2, 'Am'), (20, ' '), (1, 'G'), (10, ' '), (1, 'C')] 
2

아니, 당신이 (가) attrgetter의 반전 기능을 할 수 없습니다 당신은 또한 그것을 호출 할 필요가있는 동안 attrgetter("isspace")(x) 그냥 x"isspace" 속성을 가져옵니다 또는 neg 연산자를 사용하는 다른 함수를 호출 할 수 있습니다. 먼저 neg부정의 의미입니다.; 예 : neg(x) < =>-x. 그리고 이것은 의 결과에 적용됩니다 0; True =>-1. 부울 부정은 operator.not_입니다. 그러나 그때조차도 이것은 귀사가 귀환 가치를 무효화하는 데 도움이되지 않을 것입니다.

대신 str.isspace에서 groupby으로 전달해야합니다. str.ispacestr 유형의 인수를 허용하는 언 바운드 메소드입니다.

반환 값이 각각의 단일 문자를 값으로 사용하여 attrgetter('isspace')이라는 반환 값을 호출한다는 것입니다. 각 호출은 바인딩 인스턴스 메소드 반환, 그들은 반드시 서로 구별되는, 서로 동일한 비교하지 않는 다른 인스턴스에 바인딩이 결합 된 각각의 방법으로

>>> attrgetter('isspace')('a') 
<built-in method isspace of str object at 0x7fb204de5110> 

을, 그 이유는 당신의 코드는 당신이 기대하는 것을하지 않습니다. 실제 값을 얻으려면, 당신은 다시 한번 전화이 방법해야 할 것 :

>>> attrgetter('isspace')('a') 
False 

이 경우를 들어 내가 완전히 itertools 도랑 것입니다. 이것은 텍스트 전용 작업이므로 일반 표현식과 re 모듈을 사용하는 것이 좋습니다.단지 길이로이를 만들기 위해 지능형리스트를 사용, 그리고

>>> import re 
>>> s = 'Am     G   C' 
>>> parts = re.split('(\s+)', s) 
>>> parts 
['Am', '     ', 'G', '   ', 'C'] 

: re.split 이미 당신이 원하는의 90 %를 달성하려고 할 때

도이 문자 대 문자를 처리 할 필요가 없습니다 문자열 튜플 : 주어진 정규 표현식에 의해

입니다
>>> [(len(i), i) for i in parts] 
[(2, 'Am'), (20, '     '), (1, 'G'), (10, '   '), (1, 'C')] 

, re.split 분할. \s+은 하나 이상의 공백 문자와 일치합니다. 일반적으로 구분 기호는 삭제되지만 정규 표현식에 하위 그룹 (...)이 포함되어 있으면 해당 하위 그룹의 내용도 일치 항목에 유지됩니다.

+0

이것은 실제로 훨씬 더 읽기 쉬운 해결책이다. 고맙습니다. –