次の文字列を想定します。
The fox jumped over the log.
に変わる:
The fox jumped over the log.
これを実現する最も簡単な(1〜2行)は何ですか?
次の文字列を想定します。
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'
string.split
あり、あらゆる種類の空白も扱います。
re.sub(' {2,}', ' ', '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でペットピーブとしてリストされているためです。
r"\s\s+"
て、すでに単一のスペースを置き換えようとしないようにする傾向があります。
"\s{2,}"
は、中程度に進んだ正規表現の動作を知らないための回避策ではなく、なぜでしょうか?
s
、新しい値を返すことに注意してください。
\s+
行が読み込ま「交換する原因となる1つのスペースで以上のスペースを」ではなく、「置き換える2つのスペースで以上のスペースを」。前者はすぐに立ち止まって、「なぜ1つのスペースを1つのスペースに置き換えるのですか?それはばかげています」と思います。私には、それは(非常にマイナーな)コードのにおいです。私は実際にそれがとにかく新しい文字列にコピーするために起こっているように、2つの間のすべてのパフォーマンスの違いがあることを期待していない、と関係なく、スペースがコピーされている場所の停止とテストを持っているから。
\s\s+
これは、TAB文字を通常のスペースに正規化しないため、お勧めしません。スペース+タブはこの方法で置き換えられます。
「\ s」で正規表現を使用し、単純なstring.split()を実行すると、改行、改行、タブなどの他の空白も削除されます。これが必要でない限り、複数のスペースのみを使用するために、これらの例を示します。
私が使用11の段落、1000の言葉、Loremのイプサムの6665バイトを現実的な時間テストおよび使用されるランダムな長さの余分なスペース全体を取得するには:
original_string = ''.join(word + (' ' * random.randint(1, 10)) for word in lorem_ipsum.split(' '))
ワンライナーは基本的に、先頭/末尾のスペースのストリップを実行し、先頭/末尾のスペースを保持します(ただしONE ;-のみ)。
# 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
注: 「 main while
バージョン」はのコピーを作成しoriginal_string
ました。最初の実行で変更すると、その後の実行の方が速くなると思います(少しだけ)。これにより時間が追加されたので、この文字列のコピーを他の2つに追加して、時間の違いがロジックのみで示されるようにしました。stmt
on timeit
インスタンスは一度だけ実行されることに注意してください。私がこれを行った元の方法では、while
ループは同じラベルで機能しましたoriginal_string
。したがって、2回目の実行では、何もすることはありません。現在の設定方法、2つの異なるラベルを使用した関数の呼び出しは問題ありません。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ループが最も速く、次にPythonic文字列分割/結合、正規表現が後部を引き上げるように見えます。
自明ではない文字列の場合、もう少し検討すべきことがあるようです。32ビット2.7?それは救助の正規表現です!2.7 64ビット?while
ループはまともなマージンにより、最高です。32ビット3.2の場合は、「proper」を使用しjoin
ます。64ビット3.3、while
ループに行きます。再び。
最終的には、必要に応じて/場所/必要に応じてパフォーマンスを向上させることができますが、常にマントラを覚えておくことをお勧めします。
IANAL、YMMV、Caveat Emptor!
' '.join(the_string.split())
これは通常の使用例であるため、単純なものをテストしていただければ幸いですが、作業に感謝します!
' '.join(p for p in s.split(' ') if p)
<-まだ先頭/末尾のスペースが失われていますが、複数のスペースが含まれています。それらを維持するには、次のようにする必要がありますparts = s.split(' '); (' ' if not parts[0] else '') + ' '.join(p for p in s.split(' ') if p) + (' ' if not parts[-1] else '')
!
Paul McGuireのコメントに同意する必要があります。私に、
' '.join(the_string.split())
正規表現を打ち消すよりもはるかに好ましい。
私の測定(LinuxおよびPython 2.5)は、split-then-joinが "re.sub(...)"を実行する場合よりも約5倍速く、正規表現を1回プリコンパイルして操作を実行した場合でも3倍速いことを示しています。複数回。そして、それは理解しやすい任意の措置によってである- ずっとよりPython的。
場合によっては、連続するすべての空白文字を、その文字の単一のインスタンスで置き換えることが望ましい場合があります。これを行うには、後方参照付きの正規表現を使用します。
(\s)\1{1,}
空白文字に一致し、その後にその文字が1回以上出現します。これで、最初のグループ(\1
)を一致の代わりに指定するだけです。
これを関数にラップします:
import re
def normalize_whitespace(string):
return re.sub(r'(\s)\1{1,}', r'\1', string)
>>> normalize_whitespace('The fox jumped over the log.')
'The fox jumped over the log.'
>>> normalize_whitespace('First line\t\t\t \n\n\nSecond line')
'First line\t \nSecond line'
Python開発者向けのソリューション:
import re
text1 = 'Python Exercises Are Challenging Exercises'
print("Original string: ", text1)
print("Without extra spaces: ", re.sub(' +', ' ', text1))
出力:
Original string: Python Exercises Are Challenging Exercises
Without extra spaces: Python Exercises Are Challenging Exercises
ユーザーが生成した文字列で取得できる最速は次のとおりです。
if ' ' in text:
while ' ' in text:
text = text.replace(' ', ' ')
短絡により、pythonlarryの包括的な回答よりもわずかに速くなります。効率性を重視し、シングルスペースバリエーションの余分な空白を厳密に除外する場合は、この方法を使用してください。
まったく驚くべきこと-投稿された他のすべてのソリューションよりもはるかに高速になる単純な関数を投稿した人はいません。ここに行く:
def compactSpaces(s):
os = ""
for c in s:
if c != " " or os[-1] != " ":
os += c
return os
処理中の空白である場合、Noneで分割しても、戻り値に空の文字列は含まれません。
string = 'This is a string full of spaces and taps'
string = string.split(' ')
while '' in string:
string.remove('')
string = ' '.join(string)
print(string)
結果:
これはスペースとタップでいっぱいの文字列です
単語間の先頭、末尾、余分な空白を考慮して空白を削除するには、次を使用します。
(?<=\s) +|^ +(?=\s)| (?= +[\n\0])
1つ目or
は先頭の空白をor
扱い、2つ目は文字列の先頭の空白を扱い、最後の1つは末尾の空白を扱います。
使用を証明するために、このリンクからテストを提供します。
https://regex101.com/r/meBYli/4
これはre.split関数で使用されます。
私は大学で使用した簡単な方法を持っています。
line = "I have a nice day."
end = 1000
while end != 0:
line.replace(" ", " ")
end -= 1
これにより、すべての2つのスペースが1つのスペースに置き換えられ、1000回実行されます。つまり、2000の追加スペースを確保でき、引き続き機能します。:)
私は分割せずに簡単な方法を持っています:
a = "Lorem Ipsum Darum Diesrum!"
while True:
count = a.find(" ")
if count > 0:
a = a.replace(" ", " ")
count = a.find(" ")
continue
else:
break
print(a)
import re
Text = " You can select below trims for removing white space!! BR Aliakbar "
# trims all white spaces
print('Remove all space:',re.sub(r"\s+", "", Text), sep='')
# trims left space
print('Remove leading space:', re.sub(r"^\s+", "", Text), sep='')
# trims right space
print('Remove trailing spaces:', re.sub(r"\s+$", "", Text), sep='')
# trims both
print('Remove leading and trailing spaces:', re.sub(r"^\s+|\s+$", "", Text), sep='')
# replace more than one white space in the string with one white space
print('Remove more than one space:',re.sub(' +', ' ',Text), sep='')
結果:
すべてのスペースを削除:ホワイトスペースを削除するために以下のトリムを選択できます!! BRAliakbar先頭のスペースを削除:空白を削除するためにトリムの下を選択できます!! BR Aliakbar
後続スペースの削除:空白を削除するためにトリムの下を選択できます!! BR Aliakbar先頭と末尾のスペースを削除します:空白を削除するためにトリムの下を選択できます!! BR Aliakbar複数のスペースを削除:空白を削除するために、トリムの下を選択できます!! BRアリアクバル
他の例についてはあまり読んでいませんが、連続する複数のスペース文字を統合するためのこのメソッドを作成しました。
ライブラリは使用せず、スクリプトの長さの点では比較的長いですが、複雑な実装ではありません。
def spaceMatcher(command):
"""
Function defined to consolidate multiple whitespace characters in
strings to a single space
"""
# Initiate index to flag if more than one consecutive character
iteration
space_match = 0
space_char = ""
for char in command:
if char == " ":
space_match += 1
space_char += " "
elif (char != " ") & (space_match > 1):
new_command = command.replace(space_char, " ")
space_match = 0
space_char = ""
elif char != " ":
space_match = 0
space_char = ""
return new_command
command = None
command = str(input("Please enter a command ->"))
print(spaceMatcher(command))
print(list(spaceMatcher(command)))