Menghapus semua karakter non-numerik dari string dengan Python


Jawaban:


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

89
itu bisa re.sub (r "\ D", "", "sdkjh987978asd098as0980a98sd")
— newacct

2
dan itu bisa berupa: dari impor kembali sub
— James Koss

89

Tidak yakin apakah ini cara yang paling efisien, tetapi:

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

Bagian ini ''.joinberarti menggabungkan semua karakter yang dihasilkan bersama tanpa karakter di antaranya. Kemudian sisanya adalah pemahaman daftar, di mana (seperti yang mungkin Anda bisa tebak) kita hanya mengambil bagian-bagian dari string yang sesuai dengan kondisi isdigit.


1
Itu sebaliknya. Saya pikir maksud Anda "tidak c.isdigit ()"
— Ryan R. Rosario

7
Hapus semua non-numerik == pertahankan hanya angka.
— Mark Rushakoff

10
Saya suka bahwa pendekatan ini tidak perlu menarik kembali, untuk fungsi sederhana ini.
— triunenature

Perhatikan bahwa tidak seperti implementasi menggunakan str.translate, solusi ini bekerja di kedua python 2.7 dan 3.4. Terima kasih!
— Alex

1
Saya lebih suka alternatif ini. Menggunakan regex sepertinya berlebihan bagi saya.
— alfredocambera

18

Ini harus berfungsi untuk objek string dan unicode di Python2, dan string dan byte di Python3:

# 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

Hanya untuk menambahkan opsi lain ke dalam campuran, ada beberapa konstanta yang berguna di dalam stringmodul. Meskipun lebih bermanfaat dalam kasus lain, mereka dapat digunakan di sini.

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

Ada beberapa konstanta dalam modul, termasuk:

  • ascii_letters (abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ)
  • hexdigits (0123456789abcdefABCDEF)

Jika Anda menggunakan konstanta-konstanta ini dengan berat, ada baiknya untuk menyamarkannya menjadi a frozenset. Itu memungkinkan pencarian O (1), bukan O (n), di mana n adalah panjang konstanta untuk string asli.

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

'' .join (c untuk c di "abc123def456" jika c.isdigit ()) bekerja di python saya 3.4
— Eino Mäkitalo

7

@Ned Batchelder dan @newacct memberikan jawaban yang benar, tetapi ...

Untuk jaga-jaga jika Anda memiliki koma (,) desimal (.) Di string Anda:

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

5

Pendekatan tercepat, jika Anda perlu melakukan lebih dari satu atau dua operasi penghapusan seperti itu (atau bahkan hanya satu, tetapi pada string yang sangat panjang! -), adalah bergantung pada translatemetode string, meskipun perlu persiapan:

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

The translateMetode berbeda, dan mungkin anak laki-laki lebih sederhana sederhana untuk digunakan, pada string Unicode daripada di string byte, btw:

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

Anda mungkin ingin menggunakan kelas pemetaan daripada dict yang sebenarnya, terutama jika string Unicode Anda berpotensi berisi karakter dengan nilai ord yang sangat tinggi (yang akan membuat dict terlalu besar ;-). Sebagai contoh:

>>> 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) Jangan angka ajaib kode keras; s / 65536 / sys.maxunicode / (2) Dict itu tanpa syarat "terlalu besar" karena input "berpotensi" berisi (sys.maxunicode - number_of_non_numeric_chars)entri. (3) pertimbangkan apakah string.digits mungkin tidak cukup yang mengarah pada kebutuhan untuk membuka modul unicodedata (4) pertimbangkan re.sub (r '(? U) \ D +', u '', teks) untuk kesederhanaan dan potensi mempercepat.
— John Machin

2

Banyak jawaban yang benar tetapi jika Anda menginginkannya dalam float, langsung, tanpa menggunakan regex:

x= '$123.45M'

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

123.45

Anda dapat mengubah titik koma tergantung pada kebutuhan Anda.

ubah untuk ini jika Anda tahu nomor Anda bilangan bulat

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

1123

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.