การลบอักขระที่ไม่ใช่ตัวเลขทั้งหมดออกจากสตริงใน Python


คำตอบ:


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

90
ที่อาจเป็น re.sub (r "\ D", "", "sdkjh987978asd098as0980a98sd")
newacct

3
และอาจเป็น: จากการนำเข้าย่อยอีกครั้ง
James Koss

90

ไม่แน่ใจว่านี่เป็นวิธีที่มีประสิทธิภาพมากที่สุดหรือไม่ แต่:

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

''.joinส่วนวิธีการที่จะรวมทุกตัวละครที่เกิดขึ้นร่วมกันโดยไม่มีอักขระใด ๆ ในระหว่าง จากนั้นส่วนที่เหลือเป็นความเข้าใจของรายการโดยที่ (ตามที่คุณคาดเดาได้) เราจะเอาเฉพาะส่วนของสตริงที่ตรงกับเงื่อนไขisdigitเท่านั้น


1
นั่นตรงกันข้าม ฉันคิดว่าคุณหมายถึง "ไม่ใช่ c.isdigit ()"
Ryan R. Rosario

7
ลบทั้งหมดที่ไม่ใช่ตัวเลข == เก็บเฉพาะตัวเลข
Mark Rushakoff

10
ฉันชอบที่วิธีการนี้ไม่จำเป็นต้องดึงอีกครั้งสำหรับฟังก์ชั่นที่เรียบง่ายนี้
triunenature

โปรดทราบว่าไม่เหมือนกับการนำไปใช้โดยใช้ str.translate โซลูชันนี้ทำงานได้ทั้ง python 2.7 และ 3.4 ขอบคุณ!
Alex

1
ฉันชอบทางเลือกนี้ ใช้ regex ดูเหมือน overkill สำหรับฉัน
alfredocambera

18

สิ่งนี้จะใช้ได้ทั้งกับสตริงและวัตถุ unicode ใน Python2 และทั้งสตริงและไบต์ใน 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

เพียงเพื่อเพิ่มตัวเลือกอื่นในการผสมมีค่าคงที่ที่มีประโยชน์หลายรายการในstringโมดูล แม้ว่าจะมีประโยชน์มากกว่าในกรณีอื่น ๆ แต่ก็สามารถใช้ที่นี่ได้

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

มีหลายค่าคงที่ในโมดูลรวมถึง:

  • ascii_letters (abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ)
  • hexdigits (0123456789abcdefABCDEF)

frozensetหากคุณกำลังใช้คงที่เหล่านี้อย่างมากก็สามารถจะคุ้มค่าที่จะแอบแฝงพวกเขาไป ที่ทำให้การค้นหา O (1) มากกว่า O (n) โดยที่ n คือความยาวของค่าคงที่สำหรับสตริงดั้งเดิม

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

'' .join (c สำหรับ c ใน "abc123def456" ถ้า c.isdigit ()) ทำงานใน python ของฉัน 3.4
Eino Mäkitalo

7

@Ned Batchelder และ @newacct ให้คำตอบที่ถูกต้อง แต่ ...

ในกรณีที่คุณมีเครื่องหมายจุลภาค (,) ทศนิยม (.) ในสตริงของคุณ:

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

5

วิธีที่เร็วที่สุดหากคุณต้องการดำเนินการลบมากกว่าหนึ่งหรือสองครั้ง (หรือแม้แต่เพียงครั้งเดียว แต่ใช้สตริงที่ยาวมาก! -) คือต้องพึ่งพาtranslateวิธีการของสตริงแม้ว่าจะต้องมีการเตรียมการบางอย่าง:

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

translateวิธีการที่แตกต่างกันและอาจตาดง่ายง่ายต่อการใช้งานในสาย Unicode มากกว่าที่เป็นอยู่ในสายไบต์ครับ:

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

คุณอาจต้องการใช้คลาสการแมปมากกว่า dict จริงโดยเฉพาะอย่างยิ่งถ้า Unicode สตริงของคุณอาจมีอักขระที่มีค่า ord สูงมาก (ซึ่งจะทำให้ dict ใหญ่เกินไป ;-) ตัวอย่างเช่น:

>>> 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) อย่าเขียนโค้ดเวทย์มนตร์อย่างหนัก s / 65536 / sys.maxunicode / (2) dict ไม่มีเงื่อนไข "ใหญ่เกินไป" เนื่องจากอินพุต "อาจมี" อาจมี(sys.maxunicode - number_of_non_numeric_chars)รายการ (3) พิจารณาว่า string.digits อาจไม่เพียงพอที่จะนำไปสู่ความต้องการที่จะถอดรหัสเปิดโมดูล unicodedata (4) พิจารณา re.sub (r '(? u) \ D +', u '', text) เพื่อความเรียบง่ายและมีศักยภาพ ความเร็ว.
John Machin

2

หลายคำตอบที่ถูกต้อง แต่ในกรณีที่คุณต้องการลอยตัวโดยตรงโดยไม่ต้องใช้ regex:

x= '$123.45M'

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

123.45

คุณสามารถเปลี่ยนจุดสำหรับเครื่องหมายจุลภาคขึ้นอยู่กับความต้องการของคุณ

เปลี่ยนสิ่งนี้ถ้าคุณรู้ว่าหมายเลขของคุณเป็นจำนวนเต็ม

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

1123

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.