2011-01-16 46 views
57

Tôi có một số chuỗi tương tự như Current Level: 13.4 db. và tôi muốn trích xuất chỉ số dấu phẩy động. Tôi nói nổi và không thập phân vì nó đôi khi toàn bộ. RegEx có thể làm điều này hay là có cách nào tốt hơn?Cách trích xuất một số động từ một chuỗi

+0

Nó sẽ luôn luôn có một phần nguyên? Ngay cả khi nó là 0? Bạn có cần phải phù hợp với 0,4 hoặc .4? – Falmarri

+0

Tôi sẽ nói có. Đầu vào được nhập theo cách thủ công để có cơ hội không nhất quán. – Flowpoke

Trả lời

112

Nếu phao của bạn luôn được thể hiện bằng một cái gì đó ký hiệu thập phân như

>>> import re 
>>> re.findall("\d+\.\d+", "Current Level: 13.4 db.") 
['13.4'] 

có thể đủ.

Một phiên bản mạnh mẽ hơn sẽ là:

>>> re.findall(r"[-+]?\d*\.\d+|\d+", "Current Level: -13.2 db or 14.2 or 3") 
['-13.2', '14.2', '3'] 

Nếu bạn muốn xác nhận đầu vào người sử dụng, bạn có thể cách khác cũng kiểm tra một phao bằng cách bước để nó trực tiếp:

user_input = "Current Level: 1e100 db" 
for token in user_input.split(): 
    try: 
     # if this succeeds, you have your (first) float 
     print float(token), "is a float" 
    except ValueError: 
     print token, "is something else" 

# => Would print ... 
# 
# Current is something else 
# Level: is something else 
# 1e+100 is a float 
# db is something else 
+0

không phải lúc nào cũng là số thập phân. – Flowpoke

+2

're.findall (r" [- +]? \ D * \. * \ D + "," Cấp hiện tại: -13.2 db hoặc 14.2 hoặc 3 ")' '['-13.2', '14 .2 ',' 3 '] ' – JuanPablo

+1

Tôi nghĩ bạn có nghĩa là" \ d + \. \ D + "thay vì" \ d +. \ D + "trong khối mã đầu tiên của bạn. Ngay bây giờ nó sẽ trích xuất một cái gì đó như '13a4'. – abw333

0

cách tiếp cận khác mà có thể dễ đọc hơn là chuyển đổi loại đơn giản. Tôi đã thêm chức năng thay thế để bao gồm các trường hợp mọi người có thể nhập số thập phân châu Âu:

>>> for possibility in "Current Level: -13.2 db or 14,2 or 3".split(): 
...  try: 
...   str(float(possibility.replace(',', '.'))) 
...  except ValueError: 
...   pass 
'-13.2' 
'14.2' 
'3.0' 

Điều này cũng có bất lợi. Nếu ai đó nhập "1.000", điều này sẽ được chuyển thành 1. Ngoài ra, nó giả định rằng mọi người sẽ được nhập vào với khoảng trống giữa các từ. Đây không phải là trường hợp với các ngôn ngữ khác, chẳng hạn như tiếng Trung.

+0

"pin AAA 1.5V cỡ 4x bao gồm": -) –

+0

Những người dùng khủng khiếp đó! Luôn nhập dữ liệu ngớ ngẩn. TBH, tôi cố ý giữ ví dụ này minh họa hơn là mạnh mẽ. Khi tôi bắt đầu viết câu trả lời này, @ MYYN chỉ cung cấp cụm từ thông dụng trong câu trả lời được chấp nhận. Tôi muốn cung cấp một ví dụ về một cách khác để đi về mọi thứ. –

37

Bạn có thể muốn thử một cái gì đó như thế này bao gồm tất cả các căn cứ, bao gồm không dựa vào khoảng trắng sau số:

>>> import re 
>>> numeric_const_pattern = r""" 
...  [-+]? # optional sign 
...  (?: 
...   (?: \d* \. \d+) # .1 .12 .123 etc 9.1 etc 98.1 etc 
...   | 
...   (?: \d+ \.?) # 1. 12. 123. etc 1 12 123 etc 
... ) 
...  # followed by optional exponent part if desired 
...  (?: [Ee] [+-]? \d+) ? 
...  """ 
>>> rx = re.compile(numeric_const_pattern, re.VERBOSE) 
>>> rx.findall(".1 .12 9.1 98.1 1. 12. 1 12") 
['.1', '.12', '9.1', '98.1', '1.', '12.', '1', '12'] 
>>> rx.findall("-1 +1 2e9 +2E+09 -2e-9") 
['-1', '+1', '2e9', '+2E+09', '-2e-9'] 
>>> rx.findall("current level: -2.03e+99db") 
['-2.03e+99'] 
>>> 

Để dễ dàng sao chép dán:

numeric_const_pattern = '[-+]? (?: (?: \d* \. \d+) | (?: \d+ \.?))(?: [Ee] [+-]? \d+) ?' 
rx = re.compile(numeric_const_pattern, re.VERBOSE) 
rx.findall("Some example: Jr. it. was .23 between 2.3 and 42.31 seconds") 
+2

Rất tốt! Cuối cùng tôi đã tìm thấy một mô hình thực sự tốt! –

+0

Có, mẫu tốt nhất từ ​​trước tới nay cho số. Cảm ơn rất nhiều! – edisonex

+0

Thêm '(?: \ + \ S * | \ - \ s *)?' Ở phía trước cũng sẽ cho phép dấu cách giữa dấu và số. Mặc dù tôi thừa nhận điều này có lẽ không phải là "chuẩn" nhưng tôi đã thấy mẫu này "trôi nổi" trong một số tệp. – NOhs

5
re.findall(r"[-+]?\d*\.\d+|\d+", "Current Level: -13.2 db or 14.2 or 3") 

như mô tả ở trên, hoạt động thực sự tốt! Một gợi ý mặc dù:

re.findall(r"[-+]?\d*\.\d+|[-+]?\d+", "Current Level: -13.2 db or 14.2 or 3 or -3") 

cũng sẽ trở về giá trị int tiêu cực (như -3 vào cuối chuỗi này)

2

Tôi nghĩ rằng bạn sẽ tìm thấy nhiều thứ thú vị trong câu trả lời sau đây của tôi mà tôi đã làm cho một câu hỏi tương tự theo thời gian:

https://stackoverflow.com/q/5929469/551449

trong câu trả lời này, tôi đã đề xuất một mô hình cho phép một regex để đón bất kỳ loại số và kể từ khi tôi không có gì khác để thêm vào nó, tôi nghĩ nó là khá hoàn chỉnh

13

Python docs có một câu trả lời bao gồm +/-, và ký hiệu mũ

scanf() Token  Regular Expression 
%e, %E, %f, %g  [-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)? 
%i     [-+]?(0[xX][\dA-Fa-f]+|0[0-7]*|\d+) 

này biểu hiện thường xuyên không hỗ trợ định dạng quốc tế, nơi một dấu phẩy được sử dụng như là ký tự phân cách giữa phần nguyên và phân số một phần (3,14159). Trong trường hợp đó, hãy thay thế tất cả \. bằng [.,] trong regex nổi ở trên.

     Regular Expression 
International float  [-+]?(\d+([.,]\d*)?|[.,]\d+)([eE][-+]?\d+)? 
2

Bạn có thể sử dụng regex sau đây để có được số nguyên và các giá trị nổi từ một chuỗi:

re.findall(r'[\d\.\d]+', 'hello -34 42 +34.478m 88 cricket -44.3') 

['34', '42', '34.478', '88', '44.3'] 

Cảm ơn Rex

+2

Regex này cũng sẽ tìm các kết hợp không phải là số của các dấu chấm và chữ số: ''.... 1.2.3.4 ..56 ..'' sản lượng: '['....', '1.2.3.4', '. .56 .. '] ' – scottbb

Các vấn đề liên quan