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.