Sayısal olmayan tüm karakterleri Python'daki dizeden kaldırma


Yanıtlar:


267
>>> import re
>>> re.sub("[^0-9]", "", "sdkjh987978asd098as0980a98sd")
'987978098098098'

90
re.sub (r "\ D", "", "sdkjh987978asd098as0980a98sd") olabilir
newacct

3
ve bu olabilir: yeniden içe aktarma
altından

90

Bunun en etkili yol olup olmadığından emin değilim, ancak:

>>> ''.join(c for c in "abc123def456" if c.isdigit())
'123456'

''.joinBölüm araçları arasına hiçbir karakter gelmeyecek hep birlikte ortaya çıkan karakterleri birleştirmek. Sonra geri kalanı bir liste kavrayışıdır, burada (muhtemelen tahmin edebileceğiniz gibi) dizenin yalnızca koşula uyan kısımlarını alırız isdigit.


1
Tam tersini yapar. Bence "değil c.isdigit ()" demek
Ryan R. Rosario

7
Tüm sayısal olmayanları kaldır == yalnızca sayısal tut.
Mark Rushakoff

10
Bu basit işlev için bu yaklaşımın yeniden çekilmesini gerektirmediğini seviyorum.
triunenature

Str.translate kullanan uygulamaların aksine, bu çözümün hem python 2.7 hem de 3.4'te çalıştığını unutmayın. Teşekkür ederim!
Alex

1
Bu alternatifi tercih ederim. Normal ifade kullanmak bana aşırı derecede ağır geliyor.
alfredocambera

18

Bu, Python2'deki hem dizeler hem de unicode nesneler ve Python3'teki hem dizeler hem de baytlar için çalışmalıdır:

# python <3.0
def only_numerics(seq):
    return filter(type(seq).isdigit, seq)

# python ≥3.0
def only_numerics(seq):
    seq_type= type(seq)
    return seq_type().join(filter(seq_type.isdigit, seq))

9

Sadece karışıma başka bir seçenek eklemek için, stringmodül içinde birkaç yararlı sabit vardır . Diğer durumlarda daha yararlı olsa da, burada kullanılabilirler.

>>> from string import digits
>>> ''.join(c for c in "abc123def456" if c in digits)
'123456'

Modülde aşağıdakiler de dahil olmak üzere çeşitli sabitler vardır:

  • ascii_letters (AbcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ)
  • hexdigits (0123456789abcdefABCDEF)

Bu sabitleri yoğun bir şekilde kullanıyorsanız, bunları a'ya dönüştürmek faydalı olabilir frozenset. Bu, n, orijinal dizeler için sabitin uzunluğu olan O (n) yerine O (1) aramalarını mümkün kılar.

>>> digits = frozenset(digits)
>>> ''.join(c for c in "abc123def456" if c in digits)
'123456'

'' .join (c.isdigit () 'de çalışırsa "abc123def456" içinde c için c) 3.4
Eino Mäkitalo

7

@Ned Batchelder ve @newacct doğru cevabı verdi, ama ...

Dizenizde virgül (,) ondalık (.) Varsa:

import re
re.sub("[^\d\.]", "", "$1,999,888.77")
'1999888.77'

5

En hızlı yaklaşım, sadece bir veya ikiden fazla bu tür kaldırma işlemlerini (veya sadece bir tane, ancak çok uzun bir dizede! -) gerçekleştirmeniz translategerekiyorsa, biraz hazırlık gerektirmesine rağmen, dizelerin yöntemine güvenmektir :

>>> import string
>>> allchars = ''.join(chr(i) for i in xrange(256))
>>> identity = string.maketrans('', '')
>>> nondigits = allchars.translate(identity, string.digits)
>>> s = 'abc123def456'
>>> s.translate(identity, nondigits)
'123456'

translateYöntem, bayt dizeleri üzerinde btw daha Unicode dizeleri üzerinde, kullanımı daha basit belki biraz daha basit farklıdır ve:

>>> unondig = dict.fromkeys(xrange(65536))
>>> for x in string.digits: del unondig[ord(x)]
... 
>>> s = u'abc123def456'
>>> s.translate(unondig)
u'123456'

Özellikle Unicode dizeniz potansiyel olarak çok yüksek ord değerlerine sahip karakterler içeriyorsa (bu, dikmeyi aşırı büyük hale getirir ;-); gerçek bir dikte yerine bir eşleme sınıfı kullanmak isteyebilirsiniz. Örneğin:

>>> class keeponly(object):
...   def __init__(self, keep): 
...     self.keep = set(ord(c) for c in keep)
...   def __getitem__(self, key):
...     if key in self.keep:
...       return key
...     return None
... 
>>> s.translate(keeponly(string.digits))
u'123456'
>>> 

2
(1) Sihirli numaraları zor kodlamayın; s / 65536 / sys.maxunicode / (2) Girdi "potansiyel olarak" (sys.maxunicode - number_of_non_numeric_chars)girişler içerebileceğinden, söz konusu koşul koşulsuz olarak "aşırı büyük" . (3) string.digits öğesinin unicodedata modülünü açmak için yeterli olup olmadığını düşünün (4) basitlik ve potansiyel için re.sub (r '(? U) \ D +', u '', metin) hız.
John Machin

2

Birçok doğru cevap, ancak bir floatta, regex kullanmadan doğrudan istediğinizde:

x= '$123.45M'

float(''.join(c for c in x if (c.isdigit() or c =='.'))

123,45

İhtiyaçlarınıza bağlı olarak virgül için noktayı değiştirebilirsiniz.

numaranızın bir tam sayı olduğunu biliyorsanız bunun için değiştirin

x='$1123'    
int(''.join(c for c in x if c.isdigit())

1123

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.