Bu dizeyi varsayalım:
The fox jumped over the log.
Dönüşmek:
The fox jumped over the log.
Listelere ayrılmadan ve listelere girmeden bunu başarmak için en basit (1-2 satır) nedir?
Bu dizeyi varsayalım:
The fox jumped over the log.
Dönüşmek:
The fox jumped over the log.
Listelere ayrılmadan ve listelere girmeden bunu başarmak için en basit (1-2 satır) nedir?
Yanıtlar:
>>> import re
>>> re.sub(' +', ' ', 'The quick brown fox')
'The quick brown fox'
string.split
her türlü beyaz alanı da ele alır.
re.sub(' {2,}', ' ', 'The quick brown fox')
etmek tek boşluk tek boşluk gereksiz değiştirmeler önlemek .
foo
dizeniz:
" ".join(foo.split())
Bu, "tüm boşluk karakterlerini (boşluk, sekme, yeni satır, dönüş, form besleme )" kaldırdığına dikkat edin ( hhsaffar sayesinde yorumlara bakın). Yani, "this is \t a test\n"
etkili bir şekilde sonuçlanacak "this is a test"
.
import re
s = "The fox jumped over the log."
re.sub("\s\s+" , " ", s)
veya
re.sub("\s\s+", " ", s)
virgülden önceki boşluk , kullanıcılarda Martin Thoma tarafından belirtildiği gibi , PEP 8'de bir evcil hayvan huşu olarak listelendiğinden .
r"\s\s+"
zaten tek boşlukları değiştirmeye çalışmaz.
"\s{2,}"
orta düzeyde gelişmiş normal ifade davranışını bilmemek için bir geçici çözüm yerine?
s
, ancak yeni değeri döndürdüğünü unutmayın.
\s+
satırın " iki veya daha fazla boşluğu bir boşlukla değiştir" yerine " bir veya daha fazla boşluğu boşlukla değiştir" yazmasına neden olur . İlki derhal durmamı ve "Neden bir alanı neden bir boşlukla değiştiriyorsun? Bu aptalca" diye düşünüyor. Bana göre bu çok küçük bir kod kokusu. Aslında yine yeni bir dizeye kopyalıyor gidiyor gibi ikisi arasında hiç bir performans farkı olmasını bekliyoruz olmaz ve ne olursa olsun uzay kopyalanan nereye durağı ve test vardır den .
\s\s+
çünkü bu bir SEKME karakterini normal bir alana geri döndürmez. bir SPACE + SEKME bu şekilde değiştirilir.
"\ S" ile normal ifadeler kullanmak ve basit string.split () yapmak aynı zamanda yeni satırlar, satır başları, sekmeler gibi boşlukları da kaldıracaktır. Bu istenmedikçe, sadece birden çok boşluk yapmak için , bu örnekleri sunuyorum.
Kullandığım 11 paragraflar, 1000 kelime, Ipsum 6665 bayt gerçekçi zaman testleri ve kullanılan rastgele uzunlukta fazladan boşluklar boyunca almak için:
original_string = ''.join(word + (' ' * random.randint(1, 10)) for word in lorem_ipsum.split(' '))
Tek astar esasen herhangi bir önde gelen / sondaki boşluklardan oluşan bir şerit yapar ve önde gelen / sondaki alanı korur (ancak yalnızca 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
Not: " Ana unutmayın while
sürümü" bir kopyasını yaptı, bir original_string
kez ilk çalıştırmada değiştirildiğine inanıyorum, art arda çalışır daha hızlı olurdu (eğer sadece biraz). Bu zaman ekledikçe, zamanları sadece mantıkta farkı göstermek için bu dize kopyasını diğer ikiye ekledim. stmt
üzerindeki timeit
durumlarda sadece bir kez çalıştırılacaktır ; Bunu ilk yaptığım şekilde, while
döngü aynı etiket üzerinde çalıştı original_string
, bu yüzden ikinci çalışma, yapacak bir şey olmayacaktı. Şimdi ayarlanma şekli, iki farklı etiket kullanarak bir işlevi çağırmak sorun değil. assert
Her bir yinelemede bir şeyi değiştirdiğimizi doğrulamak için tüm çalışanlara ifadeler ekledim (şüpheli olanlar için). Örneğin, bunu değiştirin;
# 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
Önemsiz dize için, bir while döngüsü en hızlı, ardından Pythonic string-split / join ve regex'in arkaya doğru çekildiği anlaşılıyor.
Önemsiz dizeler için dikkate alınması gereken biraz daha fazla şey var gibi görünüyor. 32-bit 2.7? Kurtarmaya düzenli! 2.7 64-bit? Bir while
döngü en iyi, iyi bir farkla. 32-bit 3.2, "uygun" ile gidin join
. 64-bit 3.3, bir while
döngü için gidin . Tekrar.
Sonunda, gerekirse / nerede / gerektiğinde performansı artırabilir , ancak mantrayı hatırlamak her zaman en iyisidir :
IANAL, YMMV, Uyarıcı Emptor!
' '.join(the_string.split())
zamanki kullanım durumu olduğu için basit test etseydiniz tercih ederdim ama çalışmanız için teşekkür etmek isterim!
' '.join(p for p in s.split(' ') if p)
<- hala kayıp kurşun / sondaki boşlukları kaybettiler, ancak birden fazla boşluk muhasebeleştirdiler. Onları tutmak için, beğenmelisin parts = s.split(' '); (' ' if not parts[0] else '') + ' '.join(p for p in s.split(' ') if p) + (' ' if not parts[-1] else '')
!
Paul McGuire'ın yorumuna katılıyorum. Bana göre,
' '.join(the_string.split())
regex'i kırbaçlamak için büyük ölçüde tercih edilir.
Ölçümlerim (Linux ve Python 2.5) split-then-join öğesinin "re.sub (...)" yapmasından neredeyse beş kat daha hızlı olduğunu ve normal ifadeyi bir kez derleyip işlemi gerçekleştirdiğinizde yine de üç kat daha hızlı olduğunu gösteriyor bir kaç sefer. Ve herhangi bir önlemle anlaşılması daha kolaydır - çok daha Pythonic.
import re
string = re.sub('[ \t\n]+', ' ', 'The quick brown \n\n \t fox')
Bu, tüm sekmeleri, yeni çizgileri ve tek boşluklu birden çok beyaz boşluğu kaldıracaktır.
Aşağıdaki yöntemi denedim ve hatta gibi aşırı dava ile çalışır:
str1=' I live on earth '
' '.join(str1.split())
Ancak düzenli bir ifadeyi tercih ederseniz şu şekilde yapılabilir:
re.sub('\s+', ' ', str1)
Her ne kadar sondaki ve sondaki boşluğu kaldırmak için bazı ön işlemler yapılmalıdır.
Bazı durumlarda, her boşluk karakterinin ardışık tekrarlarını o karakterin tek bir örneğiyle değiştirmek arzu edilir . Bunu yapmak için backreferences içeren normal bir ifade kullanırsınız.
(\s)\1{1,}
boşluk karakteriyle eşleşir, ardından o karakterin bir veya daha fazla tekrarını izler. Şimdi, tek yapmanız gereken ilk grubu ( \1
) eşleşmenin yerine koymaktır.
Bunu bir işlevle sarma:
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'
Bir cümle öncesi, sonrası ve içindeki tüm fazla boşlukları kaldırmak için bir kod satırı:
sentence = " The fox jumped over the log. "
sentence = ' '.join(filter(None,sentence.split(' ')))
Açıklama:
* Kalan öğeler kelime veya noktalama işaretli kelimeler vb. Olmalıdır. Bunu kapsamlı bir şekilde test etmedim, ancak bu iyi bir başlangıç noktası olmalı. Herşey gönlünce olsun!
Python geliştiricileri için çözüm:
import re
text1 = 'Python Exercises Are Challenging Exercises'
print("Original string: ", text1)
print("Without extra spaces: ", re.sub(' +', ' ', text1))
Çıktı:
Original string: Python Exercises Are Challenging Exercises
Without extra spaces: Python Exercises Are Challenging Exercises
Kullanıcı tarafından oluşturulan dizeler için en hızlısı:
if ' ' in text:
while ' ' in text:
text = text.replace(' ', ' ')
Kısa devre, pythonlarry'nin kapsamlı cevabından biraz daha hızlı hale getirir . Verimlilik peşindeyseniz ve kesinlikle tek alan çeşitliliğinin ekstra boşluklarını ayıklamak istiyorsanız bunun için gidin .
Oldukça şaşırtıcı - kimse TÜM diğer yayınlanan çözümler çok daha hızlı olacak basit bir fonksiyon gönderdi. İşte gidiyor:
def compactSpaces(s):
os = ""
for c in s:
if c != " " or os[-1] != " ":
os += c
return os
Eğer uğraştığınız boşluksa, Hiçbiri'ne bölmek döndürülen değere boş bir dize eklemez.
string = 'This is a string full of spaces and taps'
string = string.split(' ')
while '' in string:
string.remove('')
string = ' '.join(string)
print(string)
Sonuçlar :
Bu boşluklar ve musluklar ile dolu bir dizedir
Kelimeler arasında aradaki boşluk, sondaki ve fazladan beyaz boşluk göz önünde bulundurarak beyaz boşluğu kaldırmak için şunu kullanın:
(?<=\s) +|^ +(?=\s)| (?= +[\n\0])
Birincisi or
, önde gelen beyaz boşlukla, ikincisi, önde gelen beyaz boşlukla or
başlar ve sonuncusu, takip eden beyaz boşlukla ilgilidir.
Kullanım kanıtı için bu bağlantı size bir test sunacaktır.
https://regex101.com/r/meBYli/4
Bu, re.split işleviyle birlikte kullanılacaktır .
Üniversitede kullandığım basit yöntemim var.
line = "I have a nice day."
end = 1000
while end != 0:
line.replace(" ", " ")
end -= 1
Bu, her çift boşluğu tek bir boşlukla değiştirecek ve 1000 kez yapacak. Bu, 2000 ekstra alana sahip olabileceğiniz ve yine de çalışacağınız anlamına gelir. :)
Bölmeden basit bir yöntem var:
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='')
Sonuç:
Tüm boşluğu kaldır: Beyaz boşluğu kaldırmak için aşağıdan aşağı doğru !! BRAliakbar Önde gelen boşluğu kaldır: Beyaz boşluğu kaldırmak için aşağıdaki kırpmaları seçebilirsiniz !! BR Aliakbar
Sondaki boşlukları kaldır: Beyaz boşluğu kaldırmak için aşağıdaki kaplamaları seçebilirsiniz !! BR Aliakbar Önde gelen ve arkadaki boşlukları kaldırın: Beyaz alanı kaldırmak için aşağıdaki kaplamaları seçebilirsiniz !! BR Aliakbar Birden fazla alanı kaldırma: Beyaz alanı kaldırmak için aşağıdaki kenarları seçebilirsiniz !! BR Aliakbar
Diğer örneklere çok fazla şey okumadım, ancak birkaç ardışık boşluk karakterini birleştirmek için bu yöntemi oluşturdum.
Herhangi bir kütüphane kullanmaz ve kod uzunluğu açısından nispeten uzun olsa da, karmaşık bir uygulama değildir:
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)))