2009-08-08 14 views

Odpowiedz

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

które mogłyby być re.sub (r "\ D", "", "sdkjh987978asd098as0980a98sd") – newacct

59

Nie jestem pewien, czy jest to najbardziej skuteczny sposób, ale:

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

''.join część znaczy połączyć wszystkie wynikowe znaki razem bez żadnych znaków pomiędzy nimi. Reszta to zrozumienie listy, gdzie (jak można się domyślać) bierzemy tylko części łańcucha, które pasują do warunku isdigit.

+1

To robi przeciwieństwo. Myślę, że masz na myśli "not c.isdigit()" –

+7

Usuń wszystkie nieliczbowe == zachowaj tylko cyfry. –

+7

Podoba mi się, że to podejście nie wymaga wciągania, dla tej prostej funkcji. – triunenature

4

Najszybszy podejście, jeśli trzeba wykonać więcej niż jednego lub dwóch takich operacji usuwania (lub nawet tylko jeden, ale na bardzo długi ciąg -!), Ma polegać na metodzie łańcuchów translate, mimo że nie potrzebują prep:

>>> 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' 

Sposób translate jest inna i może odrobinę prostsze prostsze w użyciu, na Unicode, niż jest na ciągi bajtów, btw:

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

Możesz chcieć użyć klasy odwzorowania, a nie faktycznego dicta, szczególnie jeśli Twój ciąg znaków Unicode może zawierać znaki o bardzo wysokich wartościach (co spowodowałoby, że dict byłby zbyt duży ;-). Na przykład:

>>> 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' 
>>> 
+1

(1) Nie koduj liczb magicznych; s/65536/sys.maxunicode/(2) Dict jest bezwarunkowo "przesadnie duży", ponieważ wejście "może potencjalnie" zawierać wpisy '(sys.maxunicode - number_of_non_numeric_chars)'. (3) rozważ, czy string.digits może być niewystarczające, co prowadzi do potrzeby złamania modułu unicodedata (4), rozważając re.sub (r '(? U) \ D +', u '', text) dla prostoty i potencjału prędkość. –

12

ten powinien działać na smyczki i obiektów Unicode:

# 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)) 
+0

i tylko w python 2.x – SilentGhost

+1

Dziękuję za przypomnienie, SilentGhost. – tzot

+1

Masz backbash, ale SO nie pozwoli mi tego naprawić. –

4

Wystarczy dodać inną opcję do mieszanki, istnieje kilka przydatnych stałe w module string. Choć są one bardziej przydatne w innych przypadkach, można je tutaj wykorzystać.

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

Istnieje kilka stałe w module, w tym:

  • ascii_letters (abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ)
  • hexdigits (abcdefABCDEF)

Jeśli używasz tych stałych mocno, to może warto je ukryć na frozenset. Umożliwia to wyszukiwanie O (1), a nie O (n), gdzie n jest długością stałej oryginalnych ciągów.

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

'' .join (c dla c w "abc123def456" jeśli c.isdigit()) działa w moim pythonie 3.4 –

Powiązane problemy