[python] 문자열에서 여러 공백을 제거하는 간단한 방법이 있습니까?

이 문자열을 가정하십시오.

The   fox jumped   over    the log.

로 전환 :

The fox jumped over the log.

이것을 나누고 목록으로 만들지 않고 이것을 달성하는 가장 간단한 (1-2 줄)은 무엇입니까?



답변

>>> import re
>>> re.sub(' +', ' ', 'The     quick brown    fox')
'The quick brown fox'


답변

foo 당신의 문자열입니다 :

" ".join(foo.split())

이렇게하면 “모든 공백 문자 (공백, 탭, 줄 바꿈, 리턴, 용지 공급 )”가 제거됩니다 ( hhsaffar 덕분에 주석 참조). 즉, "this is \t a test\n"로 효과적으로 끝날 것 "this is a test"입니다.


답변

import re
s = "The   fox jumped   over    the log."
re.sub("\s\s+" , " ", s)

또는

re.sub("\s\s+", " ", s)

쉼표 전에 공간은로 표시되어 있기 때문에 애완 동물 초조PEP 8 로, 사용자가 언급 한 마틴 토마스 코멘트에.


답변

“\ s”와 함께 정규 표현식을 사용하고 간단한 string.split ()을 사용하면 줄 바꿈, 캐리지 리턴, 탭과 같은 다른 공백 제거 됩니다 . 이것이 바람직하지 않으면, 여러 공간 수행 하기 위해이 예제를 제시합니다.

나는 11 개의 문단, 1000 단어, 6665 바이트의 Lorem Ipsum 을 사용하여 현실적인 시간 테스트를 받고 임의 길이의 여분의 공백을 사용했습니다.

original_string = ''.join(word + (' ' * random.randint(1, 10)) for word in lorem_ipsum.split(' '))

원 라이너는 본질적으로 모든 선행 / 트레일 공간을 제거하며 선행 / 트레일 공간을 유지합니다 (단 하나의 ;-).

# setup = '''

import re

def while_replace(string):
    while '  ' in string:
        string = string.replace('  ', ' ')

    return string

def re_replace(string):
    return re.sub(r' {2,}' , ' ', string)

def proper_join(string):
    split_string = string.split(' ')

    # To account for leading/trailing spaces that would simply be removed
    beg = ' ' if not split_string[ 0] else ''
    end = ' ' if not split_string[-1] else ''

    # versus simply ' '.join(item for item in string.split(' ') if item)
    return beg + ' '.join(item for item in split_string if item) + end

original_string = """Lorem    ipsum        ... no, really, it kept going...          malesuada enim feugiat.         Integer imperdiet    erat."""

assert while_replace(original_string) == re_replace(original_string) == proper_join(original_string)

#'''

# while_replace_test
new_string = original_string[:]

new_string = while_replace(new_string)

assert new_string != original_string

# re_replace_test
new_string = original_string[:]

new_string = re_replace(new_string)

assert new_string != original_string

# proper_join_test
new_string = original_string[:]

new_string = proper_join(new_string)

assert new_string != original_string

참고 : while버전”은 original_string첫 번째 실행에서 일단 수정되면 연속 실행이 더 빠를 것이라고 생각합니다. 시간이 추가됨에 따라이 문자열 복사본을 다른 두 개에 추가하여 시간에 논리의 차이 만 표시했습니다. main stmton timeit인스턴스는 한 번만 실행됩니다 . 내가 원래했던 방식으로 while루프는 동일한 레이블에서 작동 original_string하므로 두 번째 실행에서는 할 일이 없습니다. 두 가지 레이블을 사용하여 함수를 호출하여 지금 설정하는 방식은 문제가되지 않습니다. assert모든 작업자에게 성명을 추가 하여 모든 반복 작업 (모호한 사람들을 위해)마다 무언가를 변경했는지 확인했습니다. 예를 들어, 이것으로 바꾸면 깨집니다.

# while_replace_test
new_string = original_string[:]

new_string = while_replace(new_string)

assert new_string != original_string # will break the 2nd iteration

while '  ' in original_string:
    original_string = original_string.replace('  ', ' ')

Tests run on a laptop with an i5 processor running Windows 7 (64-bit).

timeit.Timer(stmt = test, setup = setup).repeat(7, 1000)

test_string = 'The   fox jumped   over\n\t    the log.' # trivial

Python 2.7.3, 32-bit, Windows
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.001066 |   0.001260 |   0.001128 |   0.001092
     re_replace_test |   0.003074 |   0.003941 |   0.003357 |   0.003349
    proper_join_test |   0.002783 |   0.004829 |   0.003554 |   0.003035

Python 2.7.3, 64-bit, Windows
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.001025 |   0.001079 |   0.001052 |   0.001051
     re_replace_test |   0.003213 |   0.004512 |   0.003656 |   0.003504
    proper_join_test |   0.002760 |   0.006361 |   0.004626 |   0.004600

Python 3.2.3, 32-bit, Windows
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.001350 |   0.002302 |   0.001639 |   0.001357
     re_replace_test |   0.006797 |   0.008107 |   0.007319 |   0.007440
    proper_join_test |   0.002863 |   0.003356 |   0.003026 |   0.002975

Python 3.3.3, 64-bit, Windows
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.001444 |   0.001490 |   0.001460 |   0.001459
     re_replace_test |   0.011771 |   0.012598 |   0.012082 |   0.011910
    proper_join_test |   0.003741 |   0.005933 |   0.004341 |   0.004009

test_string = lorem_ipsum
# Thanks to http://www.lipsum.com/
# "Generated 11 paragraphs, 1000 words, 6665 bytes of Lorem Ipsum"

Python 2.7.3, 32-bit
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.342602 |   0.387803 |   0.359319 |   0.356284
     re_replace_test |   0.337571 |   0.359821 |   0.348876 |   0.348006
    proper_join_test |   0.381654 |   0.395349 |   0.388304 |   0.388193

Python 2.7.3, 64-bit
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.227471 |   0.268340 |   0.240884 |   0.236776
     re_replace_test |   0.301516 |   0.325730 |   0.308626 |   0.307852
    proper_join_test |   0.358766 |   0.383736 |   0.370958 |   0.371866

Python 3.2.3, 32-bit
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.438480 |   0.463380 |   0.447953 |   0.446646
     re_replace_test |   0.463729 |   0.490947 |   0.472496 |   0.468778
    proper_join_test |   0.397022 |   0.427817 |   0.406612 |   0.402053

Python 3.3.3, 64-bit
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.284495 |   0.294025 |   0.288735 |   0.289153
     re_replace_test |   0.501351 |   0.525673 |   0.511347 |   0.508467
    proper_join_test |   0.422011 |   0.448736 |   0.436196 |   0.440318

사소한 문자열의 경우 while 루프가 가장 빠르고 파이썬 문자열 스플릿 / 조인이 있고 정규 표현식이 뒤쪽을 당기는 것처럼 보입니다.

사소한 문자열 의 경우 고려해야 할 것이 더 있습니다. 32 비트 2.7? 구조에 대한 정규식입니다! 2.7 64 비트? while루프는 상당한 차이로, 최고입니다. 32 비트 3.2는 “proper”와 함께 사용하십시오 join. 64 비트 3.3, while루프 로 이동하십시오 . 다시.

결국, 필요한 경우 / 위치 / 필요한 경우 성능을 향상시킬 수 있지만 항상 진언기억하는 것이 가장 좋습니다 .

  1. 작동하게 만들다
  2. 잘되도록하세요
  3. 빨리 해

IANAL, YMMV, Caveat Emptor!


답변

Paul McGuire의 의견에 동의해야합니다. 나에게,

' '.join(the_string.split())

정규식을 꺼내는 것보다 훨씬 좋습니다.

내 측정 (Linux 및 Python 2.5)은 split-then-join이 “re.sub (…)”를 수행하는 것보다 거의 5 배 빠르며 정규 표현식을 한 번 사전 컴파일하고 작업을 수행하면 여전히 3 배 빠름을 보여줍니다 여러 번. 그리고 그것은 훨씬 더 이해하기 쉽습니다- 훨씬 더 파이썬적인 것입니다.


답변

이전 솔루션과 유사하지만보다 구체적 : 두 개 이상의 공백을 하나로 바꿉니다.

>>> import re
>>> s = "The   fox jumped   over    the log."
>>> re.sub('\s{2,}', ' ', s)
'The fox jumped over the log.'


답변

간단한 영혼

>>> import re
>>> s="The   fox jumped   over    the log."
>>> print re.sub('\s+',' ', s)
The fox jumped over the log.