Dizeden sayılar dışındaki tüm karakterleri nasıl kaldırabilirim?
Dizeden sayılar dışındaki tüm karakterleri nasıl kaldırabilirim?
Yanıtlar:
Python 2. * 'de, en hızlı yaklaşım .translateyöntemdir:
>>> x='aaa12333bb445bb54b5b52'
>>> import string
>>> all=string.maketrans('','')
>>> nodigs=all.translate(all, string.digits)
>>> x.translate(all, nodigs)
'1233344554552'
>>>
string.maketransbu durumda aynı olan bir çeviri tablosu (uzunluk 256 dizesi) yapar ''.join(chr(x) for x in range(256))(sadece ;-) daha hızlıdır). .translateçeviri tablosunu uygular (burada allözdeşlik anlamına geldiği için anlamsızdır ) VE ikinci argümanda bulunan karakterleri siler - anahtar kısım.
.translateçok farklı Unicode dizeleri çalışır (Python 3 ve dizeleri - ben yapmak dileği soruları Python büyük salınımlı ilgi olduğu belirtilmedi!) - oldukça bu basit, oldukça bu hızlı olsa hala oldukça kullanışlı.
Geri 2. *, performans farkı etkileyici ...:
$ python -mtimeit -s'import string; all=string.maketrans("", ""); nodig=all.translate(all, string.digits); x="aaa12333bb445bb54b5b52"' 'x.translate(all, nodig)'
1000000 loops, best of 3: 1.04 usec per loop
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 loops, best of 3: 7.9 usec per loop
İşleri 7-8 kat hızlandırmak neredeyse yer fıstığı değildir, bu nedenle translateyöntem bilmeye ve kullanmaya değer. Diğer popüler RE olmayan yaklaşım ...:
$ python -mtimeit -s'x="aaa12333bb445bb54b5b52"' '"".join(i for i in x if i.isdigit())'
100000 loops, best of 3: 11.5 usec per loop
RE'den% 50 daha yavaştır, bu nedenle .translateyaklaşım onu bir büyüklük sırasına göre yener.
Python 3'te veya Unicode için, silmek istediğiniz şey için .translatedöndürülen bir eşleme (sıralı karakterlerle, doğrudan karakterlerle değil, anahtar olarak) geçirmeniz gerekir None. Birkaç karakteri "her şeyden" silmek için bunu ifade etmenin uygun bir yolu:
import string
class Del:
def __init__(self, keep=string.digits):
self.comp = dict((ord(c),c) for c in keep)
def __getitem__(self, k):
return self.comp.get(k)
DD = Del()
x='aaa12333bb445bb54b5b52'
x.translate(DD)
ayrıca yayar '1233344554552'. Ancak, bunu xx.py içine koyarak ...:
$ python3.1 -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 loops, best of 3: 8.43 usec per loop
$ python3.1 -mtimeit -s'import xx; x="aaa12333bb445bb54b5b52"' 'x.translate(xx.DD)'
10000 loops, best of 3: 24.3 usec per loop
... bu tür bir "silme" görevi için performans avantajının kaybolduğunu ve performans düşüşüne dönüştüğünü gösterir.
x.translate(None, string.digits)aslında sonuçlanan 'aaabbbbbb'şeyin tam tersidir.
allkılıyor ... bundan emin değilim!
Şöyle kullanın re.sub:
>>> import re
>>> re.sub('\D', '', 'aas30dsa20')
'3020'
\D herhangi bir rakam olmayan karakterle eşleşir, bu nedenle yukarıdaki kod, esasen boş dize için rakam olmayan her karakterin yerini alır.
Veya şu şekilde kullanabilirsiniz filter(Python 2'de):
>>> filter(str.isdigit, 'aas30dsa20')
'3020'
Python 3'te, filtera yerine yineleyici döndürdüğünden list, aşağıdakini kullanabilirsiniz:
>>> ''.join(filter(str.isdigit, 'aas30dsa20'))
'3020'
isdigit, jeneratör ile isdigtaralarında yarı yarıya
rHam dize için kullanın :re.sub(r"\D+", "", "aas30dsa20")
s=''.join(i for i in s if i.isdigit())
Başka bir jeneratör çeşidi.
Filtre kullanabilirsiniz:
filter(lambda x: x.isdigit(), "dasdasd2313dsa")
Python3.0'da buna katılmak zorundasınız (biraz çirkin :()
''.join(filter(lambda x: x.isdigit(), "dasdasd2313dsa"))
striçin listemin py2 ve PY3 hem çalışır hale getirmek için:''.join(filter(lambda x: x.isdigit(), list("dasdasd2313dsa")))
bayer'in cevabı boyunca:
''.join(i for i in s if i.isdigit())
-bir rakam olmadığından negatif sayılar için işe yaramaz .
x.translate(None, string.digits)
dizeden tüm basamakları siler. Harfleri silmek ve rakamları saklamak için şunları yapın:
x.translate(None, string.letters)
TypeError: translate () tam olarak bir argüman alır (2 tane verilir). Bu sorunun şu anki durumunda neden kaldırıldığı oldukça sinir bozucu.
Operasyon, yorumlarda ondalık basamak tutmak istediğinden bahsediyor. Bu, saklanacak karakterleri açıkça listeleyerek re.sub yöntemiyle (ikinci ve IMHO en iyi yanıta göre) yapılabilir.
>>> re.sub("[^0123456789\.]","","poo123.4and5fish")
'123.45'
Python 3 için hızlı bir sürüm:
# xx3.py
from collections import defaultdict
import string
_NoneType = type(None)
def keeper(keep):
table = defaultdict(_NoneType)
table.update({ord(c): c for c in keep})
return table
digit_keeper = keeper(string.digits)
İşte regex ile performans karşılaştırması:
$ python3.3 -mtimeit -s'import xx3; x="aaa12333bb445bb54b5b52"' 'x.translate(xx3.digit_keeper)'
1000000 loops, best of 3: 1.02 usec per loop
$ python3.3 -mtimeit -s'import re; r = re.compile(r"\D"); x="aaa12333bb445bb54b5b52"' 'r.sub("", x)'
100000 loops, best of 3: 3.43 usec per loop
Bu yüzden benim için normal ifadeden 3 kat biraz daha hızlı. Ayrıca class Delyukarıdakinden daha hızlıdır , çünkü defaultdict(yavaş) Python yerine tüm aramalarını C'de yapar. Karşılaştırma için aynı sistemimdeki sürüm.
$ python3.3 -mtimeit -s'import xx; x="aaa12333bb445bb54b5b52"' 'x.translate(xx.DD)'
100000 loops, best of 3: 13.6 usec per loop
Çirkin ama çalışıyor:
>>> s
'aaa12333bb445bb54b5b52'
>>> a = ''.join(filter(lambda x : x.isdigit(), s))
>>> a
'1233344554552'
>>>
list(s)?
filter(lambda x: x.isdigit(), s)benim için iyi çalıştı. ... oh, çünkü Python 2.7 kullanıyorum.
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 döngü, döngü başına en iyi 3: 2,48 usec
$ python -mtimeit -s'import re; x="aaa12333bab445bb54b5b52"' '"".join(re.findall("[a-z]+",x))'
100000 döngü, döngü başına en iyi 3: 2,02 usec
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 döngü, döngü başına en iyi 3: 2,37 usec
$ python -mtimeit -s'import re; x="aaa12333bab445bb54b5b52"' '"".join(re.findall("[a-z]+",x))'
100000 döngü, döngü başına en iyi 3: 1,97 usec
Birleşmenin alttan daha hızlı olduğunu gözlemlemiştim.
Her karakteri okuyabilirsiniz. Rakamsa, cevaba ekleyin. str.isdigit() Yöntem bir karakter basamaklı olup olmadığını bilmek için bir yoldur.
your_input = '12kjkh2nnk34l34'
your_output = ''.join(c for c in your_input if c.isdigit())
print(your_output) # '1223434'
Tek bir astar değil, çok basit:
buffer = ""
some_str = "aas30dsa20"
for char in some_str:
if not char.isdigit():
buffer += char
print( buffer )
Bunu kullandım. 'letters'kurtulmak istediğiniz tüm harfleri içermelidir:
Output = Input.translate({ord(i): None for i in 'letters'}))
Misal:
Input = "I would like 20 dollars for that suit"
Output = Input.translate({ord(i): None for i in 'abcdefghijklmnopqrstuvwxzy'}))
print(Output)
Çıktı:
20