Tôi sẽ trích xuất tất cả các số có trong một chuỗi. Cái nào phù hợp hơn cho mục đích, biểu thức chính quy hay isdigit()
phương thức?
Thí dụ:
line = "hello 12 hi 89"
Kết quả:
[12, 89]
Tôi sẽ trích xuất tất cả các số có trong một chuỗi. Cái nào phù hợp hơn cho mục đích, biểu thức chính quy hay isdigit()
phương thức?
Thí dụ:
line = "hello 12 hi 89"
Kết quả:
[12, 89]
Câu trả lời:
Nếu bạn chỉ muốn trích xuất các số nguyên dương, hãy thử như sau:
>>> str = "h3110 23 cat 444.4 rabbit 11 2 dog"
>>> [int(s) for s in str.split() if s.isdigit()]
[23, 11, 2]
Tôi sẽ lập luận rằng điều này tốt hơn ví dụ regex vì ba lý do. Đầu tiên, bạn không cần một mô-đun khác; thứ hai, nó dễ đọc hơn vì bạn không cần phải phân tích ngôn ngữ mini regex; và thứ ba, nó nhanh hơn (và do đó có khả năng nhiều pythonic hơn):
python -m timeit -s "str = 'h3110 23 cat 444.4 rabbit 11 2 dog' * 1000" "[s for s in str.split() if s.isdigit()]"
100 loops, best of 3: 2.84 msec per loop
python -m timeit -s "import re" "str = 'h3110 23 cat 444.4 rabbit 11 2 dog' * 1000" "re.findall('\\b\\d+\\b', str)"
100 loops, best of 3: 5.66 msec per loop
Điều này sẽ không nhận ra số float, số nguyên âm hoặc số nguyên ở định dạng thập lục phân. Nếu bạn không thể chấp nhận những hạn chế này, câu trả lời của slim dưới đây sẽ thực hiện mẹo.
re
. Nó là một công cụ chung và mạnh mẽ (vì vậy bạn học được điều gì đó rất hữu ích). Tốc độ có phần không liên quan trong phân tích cú pháp nhật ký (rốt cuộc nó không phải là một số bộ giải số chuyên sâu), re
mô-đun nằm trong thư viện Python tiêu chuẩn và việc tải nó không ảnh hưởng gì.
mumblejumble45mumblejumble
trong đó tôi biết rằng chỉ có một số. Giải pháp đơn giản int(filter(str.isdigit, your_string))
.
str
sau đó ghi đè str
đối tượng và phương thức trong python cơ sở. Đó không phải là thực hành tốt vì bạn có thể cần nó sau này trong kịch bản.
int(filter(...))
sẽ nâng cao TypeError: int() argument must be a string...
cho Python 3.5, vì vậy bạn có thể sử dụng phiên bản cập nhật: int(''.join(filter(str.isdigit, your_string)))
để trích xuất tất cả các chữ số thành một số nguyên.
Tôi sẽ sử dụng một biểu thức chính quy:
>>> import re
>>> re.findall(r'\d+', 'hello 42 I\'m a 32 string 30')
['42', '32', '30']
Điều này cũng sẽ phù hợp với 42 từ bla42bla
. Nếu bạn chỉ muốn các số được phân tách bằng ranh giới từ (dấu cách, dấu chấm, dấu phẩy), bạn có thể sử dụng \ b:
>>> re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string 30')
['42', '32', '30']
Để kết thúc với một danh sách các số thay vì danh sách các chuỗi:
>>> [int(s) for s in re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string 30')]
[42, 32, 30]
int
qua nó và bạn đã hoàn thành. +1 đặc biệt cho phần sau. Tôi muốn đề xuất chuỗi thô ( r'\b\d+\b' == '\\b\\d+\\b'
) mặc dù.
int_list = [int(s) for s in re.findall('\\d+', 'hello 12 hi 89')]
map
.
Điều này muộn hơn một chút, nhưng bạn cũng có thể mở rộng biểu thức regex để giải thích cho ký hiệu khoa học.
import re
# Format is [(<string>, <expected output>), ...]
ss = [("apple-12.34 ba33na fanc-14.23e-2yapple+45e5+67.56E+3",
['-12.34', '33', '-14.23e-2', '+45e5', '+67.56E+3']),
('hello X42 I\'m a Y-32.35 string Z30',
['42', '-32.35', '30']),
('he33llo 42 I\'m a 32 string -30',
['33', '42', '32', '-30']),
('h3110 23 cat 444.4 rabbit 11 2 dog',
['3110', '23', '444.4', '11', '2']),
('hello 12 hi 89',
['12', '89']),
('4',
['4']),
('I like 74,600 commas not,500',
['74,600', '500']),
('I like bad math 1+2=.001',
['1', '+2', '.001'])]
for s, r in ss:
rr = re.findall("[-+]?[.]?[\d]+(?:,\d\d\d)*[\.]?\d*(?:[eE][-+]?\d+)?", s)
if rr == r:
print('GOOD')
else:
print('WRONG', rr, 'should be', r)
Cho tất cả tốt!
Ngoài ra, bạn có thể xem biểu thức chính quy tích hợp keo AWS
s = "4"
trả về không có kết quả khớp. Có thể được chỉnh sửa để cũng chăm sóc này?
[+-]?\d*[\.]?\d*(?:(?:[eE])[+-]?\d+)?
Nhóm này đưa ra một số dương tính giả ( +
đôi khi bị bắt bởi chính nó), nhưng có thể xử lý nhiều hình thức hơn, như .001
, cộng với việc nó không kết hợp các số tự động (như trong s=2+1
)
[-+]?[.]?[\d]+(?:,\d\d\d)*[\.]?\d*(?:[eE][-+]?\d+)?
- thật ngớ ngẩn với tôi ... làm sao tôi không nghĩ đến điều đó?
Tôi giả sử bạn muốn số float không chỉ là số nguyên nên tôi sẽ làm một cái gì đó như thế này:
l = []
for t in s.split():
try:
l.append(float(t))
except ValueError:
pass
Lưu ý rằng một số giải pháp khác được đăng ở đây không hoạt động với số âm:
>>> re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string -30')
['42', '32', '30']
>>> '-3'.isdigit()
False
float
thành int
.
re.findall("[-\d]+", "1 -2")
continue
thay vì pass
trong vòng lặp?
Nếu bạn biết đó sẽ chỉ là một số trong chuỗi, tức là 'xin chào 12 hi', bạn có thể thử bộ lọc.
Ví dụ:
In [1]: int(''.join(filter(str.isdigit, '200 grams')))
Out[1]: 200
In [2]: int(''.join(filter(str.isdigit, 'Counters: 55')))
Out[2]: 55
In [3]: int(''.join(filter(str.isdigit, 'more than 23 times')))
Out[3]: 23
Nhưng hãy cẩn thận !!! :
In [4]: int(''.join(filter(str.isdigit, '200 grams 5')))
Out[4]: 2005
TypeError: int() argument must be a string, a bytes-like object or a number, not 'filter'
- sửa nó bằng cách sử dụngint("".join(filter(str.isdigit, '200 grams')))
# extract numbers from garbage string:
s = '12//n,_@#$%3.14kjlw0xdadfackvj1.6e-19&*ghn334'
newstr = ''.join((ch if ch in '0123456789.-e' else ' ') for ch in s)
listOfNumbers = [float(i) for i in newstr.split()]
print(listOfNumbers)
[12.0, 3.14, 0.0, 1.6e-19, 334.0]
Tôi đang tìm kiếm một giải pháp để loại bỏ mặt nạ của chuỗi, cụ thể là từ số điện thoại của Brazil, bài đăng này không trả lời nhưng đã truyền cảm hứng cho tôi. Đây là giải pháp của tôi:
>>> phone_number = '+55(11)8715-9877'
>>> ''.join([n for n in phone_number if n.isdigit()])
'551187159877'
Sử dụng Regex dưới đây là cách
lines = "hello 12 hi 89"
import re
output = []
#repl_str = re.compile('\d+.?\d*')
repl_str = re.compile('^\d+$')
#t = r'\d+.?\d*'
line = lines.split()
for word in line:
match = re.search(repl_str, word)
if match:
output.append(float(match.group()))
print (output)
với findall
re.findall(r'\d+', "hello 12 hi 89")
['12', '89']
re.findall(r'\b\d+\b', "hello 12 hi 89 33F AC 777")
['12', '89', '777']
findall()
repl_str = re.compile('\d+.?\d*')
nên là: repl_str = re.compile('\d+\.?\d*')
Đối với một ví dụ có thể tái tạo bằng python3.7 re.search(re.compile(r'\d+.?\d*'), "42G").group()
'42G' re.search(re.compile(r'\d+\.?\d*'), "42G").group()
'42'
line2 = "hello 12 hi 89"
temp1 = re.findall(r'\d+', line2) # through regular expression
res2 = list(map(int, temp1))
print(res2)
Chào ,
bạn có thể tìm kiếm tất cả các số nguyên trong chuỗi thông qua chữ số bằng cách sử dụng biểu thức findall.
Trong bước thứ hai, tạo một danh sách res2 và thêm các chữ số được tìm thấy trong chuỗi vào danh sách này
hi vọng điêu nay co ich
Trân trọng, Diwakar Sharma
Câu trả lời này cũng chứa trường hợp khi số nổi trong chuỗi
def get_first_nbr_from_str(input_str):
'''
:param input_str: strings that contains digit and words
:return: the number extracted from the input_str
demo:
'ab324.23.123xyz': 324.23
'.5abc44': 0.5
'''
if not input_str and not isinstance(input_str, str):
return 0
out_number = ''
for ele in input_str:
if (ele == '.' and '.' not in out_number) or ele.isdigit():
out_number += ele
elif out_number:
break
return float(out_number)
Tôi ngạc nhiên khi thấy rằng chưa có ai đề cập đến việc sử dụng itertools.groupby
như là một thay thế để đạt được điều này.
Bạn có thể sử dụng itertools.groupby()
cùng với str.isdigit()
để trích xuất số từ chuỗi dưới dạng:
from itertools import groupby
my_str = "hello 12 hi 89"
l = [int(''.join(i)) for is_digit, i in groupby(my_str, str.isdigit) if is_digit]
Giá trị được giữ bởi l
sẽ là:
[12, 89]
PS: Đây chỉ là mục đích minh họa để cho thấy rằng như là một thay thế chúng ta cũng có thể sử dụng groupby
để đạt được điều này. Nhưng đây không phải là một giải pháp được đề nghị. Nếu bạn muốn đạt được điều này, bạn nên sử dụng câu trả lời được chấp nhận của fmark dựa trên việc sử dụng tính năng hiểu danh sách với str.isdigit
bộ lọc.
Để bắt các mẫu khác nhau, thật hữu ích khi truy vấn với các mẫu khác nhau.
'[\ d] + [., \ D] +'
'[\ d] * [.] [\ d] +'
'[\ D] +'
(Lưu ý: Đặt các mẫu phức tạp trước, các mẫu đơn giản khác sẽ trả về các khối của sản phẩm khai thác phức tạp thay vì sản phẩm khai thác phức tạp trả lại toàn bộ sản phẩm khai thác).
p = '[\d]+[.,\d]+|[\d]*[.][\d]+|[\d]+'
Dưới đây, chúng tôi sẽ xác nhận một mẫu có mặt re.search()
, sau đó trả về một danh sách các sản phẩm khai thác có thể lặp lại. Cuối cùng, chúng tôi sẽ in từng lần bắt bằng cách sử dụng ký hiệu ngoặc để chọn giá trị trả về của đối tượng khớp từ đối tượng khớp.
s = 'he33llo 42 I\'m a 32 string 30 444.4 12,001'
if re.search(p, s) is not None:
for catch in re.finditer(p, s):
print(catch[0]) # catch is a match object
Trả về:
33
42
32
30
444.4
12,001
Vì không ai trong số này xử lý các số tài chính trong thế giới thực trong các tài liệu excel và word mà tôi cần tìm, nên đây là biến thể của tôi. Nó xử lý ints, float, số âm, số tiền (vì nó không trả lời khi tách) và có tùy chọn bỏ phần thập phân và chỉ trả về int hoặc trả lại mọi thứ.
Nó cũng xử lý hệ thống số Laks Ấn Độ trong đó dấu phẩy xuất hiện không đều, không cách nhau 3 số.
Nó không xử lý ký hiệu khoa học hoặc số âm được đặt trong ngoặc đơn trong ngân sách - sẽ xuất hiện tích cực.
Nó cũng không trích xuất ngày. Có nhiều cách tốt hơn để tìm ngày trong chuỗi.
import re
def find_numbers(string, ints=True):
numexp = re.compile(r'[-]?\d[\d,]*[\.]?[\d{2}]*') #optional - in front
numbers = numexp.findall(string)
numbers = [x.replace(',','') for x in numbers]
if ints is True:
return [int(x.replace(',','').split('.')[0]) for x in numbers]
else:
return numbers
@jmnas, tôi thích câu trả lời của bạn, nhưng nó không tìm thấy phao. Tôi đang làm việc trên một kịch bản để phân tích mã đi đến nhà máy CNC và cần tìm cả hai kích thước X và Y có thể là số nguyên hoặc số float, vì vậy tôi đã điều chỉnh mã của bạn theo sau. Điều này tìm thấy int, float với vals tích cực và tiêu cực. Vẫn không tìm thấy các giá trị được định dạng hex nhưng bạn có thể thêm "x" và "A" đến "F" vào num_char
bộ dữ liệu và tôi nghĩ rằng nó sẽ phân tích những thứ như '0x23AC'.
s = 'hello X42 I\'m a Y-32.35 string Z30'
xy = ("X", "Y")
num_char = (".", "+", "-")
l = []
tokens = s.split()
for token in tokens:
if token.startswith(xy):
num = ""
for char in token:
# print(char)
if char.isdigit() or (char in num_char):
num = num + char
try:
l.append(float(num))
except ValueError:
pass
print(l)
Tùy chọn tốt nhất tôi tìm thấy là dưới đây. Nó sẽ trích xuất một số và có thể loại bỏ bất kỳ loại char nào.
def extract_nbr(input_str):
if input_str is None or input_str == '':
return 0
out_number = ''
for ele in input_str:
if ele.isdigit():
out_number += ele
return float(out_number)
Đối với số điện thoại, bạn có thể chỉ cần loại trừ tất cả các ký tự không có chữ số với \ D trong regex:
import re
phone_number = '(619) 459-3635'
phone_number = re.sub(r"\D", "", phone_number)
print(phone_number)