Saya akan mengekstrak semua angka yang terkandung dalam string. Mana yang lebih cocok untuk tujuan, ekspresi reguler atau isdigit()
metode?
Contoh:
line = "hello 12 hi 89"
Hasil:
[12, 89]
Saya akan mengekstrak semua angka yang terkandung dalam string. Mana yang lebih cocok untuk tujuan, ekspresi reguler atau isdigit()
metode?
Contoh:
line = "hello 12 hi 89"
Hasil:
[12, 89]
Jawaban:
Jika Anda hanya ingin mengekstrak hanya bilangan bulat positif, coba yang berikut ini:
>>> str = "h3110 23 cat 444.4 rabbit 11 2 dog"
>>> [int(s) for s in str.split() if s.isdigit()]
[23, 11, 2]
Saya berpendapat bahwa ini lebih baik daripada contoh regex karena tiga alasan. Pertama, Anda tidak perlu modul lain; kedua, ini lebih mudah dibaca karena Anda tidak perlu mengurai regex-bahasa mini; dan ketiga, lebih cepat (dan karenanya kemungkinan lebih pythonic):
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
Ini tidak akan mengenali float, bilangan bulat negatif, atau bilangan bulat dalam format heksadesimal. Jika Anda tidak dapat menerima batasan ini, jawaban ramping di bawah ini akan membantu.
re
. Ini adalah alat umum dan kuat (sehingga Anda belajar sesuatu yang sangat berguna). Kecepatan agak tidak relevan dalam parsing log (itu bukan pemecah angka intensif setelah semua), re
modul ini di perpustakaan Python standar dan tidak ada salahnya memuatnya.
mumblejumble45mumblejumble
di mana saya tahu bahwa hanya ada satu nomor. Solusinya sederhana int(filter(str.isdigit, your_string))
.
str
yang kemudian menimpa str
objek dan metode dalam basis python. Itu bukan praktik yang baik karena Anda mungkin membutuhkannya nanti dalam skrip.
int(filter(...))
akan meningkatkan TypeError: int() argument must be a string...
untuk Python 3.5, sehingga Anda dapat menggunakan versi terbaru: int(''.join(filter(str.isdigit, your_string)))
untuk mengekstraksi semua digit ke satu integer.
Saya akan menggunakan regexp:
>>> import re
>>> re.findall(r'\d+', 'hello 42 I\'m a 32 string 30')
['42', '32', '30']
Ini juga akan cocok dengan 42 dari bla42bla
. Jika Anda hanya ingin angka dibatasi oleh batas kata (spasi, titik, koma), Anda dapat menggunakan \ b:
>>> re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string 30')
['42', '32', '30']
Untuk berakhir dengan daftar nomor alih-alih daftar string:
>>> [int(s) for s in re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string 30')]
[42, 32, 30]
int
di atasnya dan Anda selesai. +1 terutama untuk bagian terakhir. Saya akan menyarankan string mentah ( r'\b\d+\b' == '\\b\\d+\\b'
).
int_list = [int(s) for s in re.findall('\\d+', 'hello 12 hi 89')]
map
.
Ini lebih dari sedikit terlambat, tetapi Anda dapat memperluas ekspresi regex ke akun notasi ilmiah juga.
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)
Semuanya baik-baik saja!
Selain itu, Anda dapat melihat regex bawaan AWS Glue
s = "4"
mengembalikan tidak cocok. Bisakah diedit juga untuk mengurus ini?
[+-]?\d*[\.]?\d*(?:(?:[eE])[+-]?\d+)?
ini memang memberikan beberapa positif palsu (mis. +
Kadang-kadang ditangkap dengan sendirinya), tetapi mampu menangani lebih banyak bentuk, seperti .001
, plus itu tidak menggabungkan angka secara otomatis (seperti dalam s=2+1
)
[-+]?[.]?[\d]+(?:,\d\d\d)*[\.]?\d*(?:[eE][-+]?\d+)?
- konyol saya ... bagaimana mungkin saya tidak memikirkan itu?
Saya berasumsi Anda ingin mengapung bukan hanya bilangan bulat, jadi saya akan melakukan sesuatu seperti ini:
l = []
for t in s.split():
try:
l.append(float(t))
except ValueError:
pass
Perhatikan bahwa beberapa solusi lain yang diposting di sini tidak bekerja dengan angka negatif:
>>> re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string -30')
['42', '32', '30']
>>> '-3'.isdigit()
False
float
ke int
.
re.findall("[-\d]+", "1 -2")
continue
alih-alih pass
di dalam loop?
Jika Anda tahu itu hanya akan menjadi satu angka dalam string, yaitu 'halo 12 hai', Anda dapat mencoba memfilter.
Sebagai contoh:
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
Tapi hati-hati !!! :
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'
- memperbaikinya dengan menggunakanint("".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]
Menggunakan Regex di bawah ini adalah caranya
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)
dengan 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*')
seharusnya: repl_str = re.compile('\d+\.?\d*')
Untuk contoh yang dapat direproduksi menggunakan 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)
Hai,
Anda dapat mencari semua bilangan bulat dalam string melalui digit dengan menggunakan ekspresi findall.
Pada langkah kedua buat daftar res2 dan tambahkan angka yang ditemukan dalam string ke daftar ini
semoga ini membantu
Salam, Diwakar Sharma
Jawaban ini juga berisi huruf besar-kecil ketika angka tersebut mengambang dalam string
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)
Saya kagum melihat bahwa belum ada yang menyebut penggunaan itertools.groupby
sebagai alternatif untuk mencapai ini.
Anda dapat menggunakan itertools.groupby()
bersama dengan str.isdigit()
untuk mengekstraksi angka dari string sebagai:
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]
Nilai yang dipegang oleh l
akan:
[12, 89]
PS: Ini hanya untuk tujuan ilustrasi untuk menunjukkan bahwa sebagai alternatif kita juga bisa menggunakan groupby
untuk mencapainya. Tapi ini bukan solusi yang disarankan. Jika Anda ingin mencapai ini, Anda harus menggunakan jawaban fmark yang diterima berdasarkan menggunakan pemahaman daftar dengan str.isdigit
sebagai filter.
Saya hanya menambahkan jawaban ini karena tidak ada yang menambahkan satu menggunakan penanganan Exception dan karena ini juga berfungsi untuk mengapung
a = []
line = "abcd 1234 efgh 56.78 ij"
for word in line.split():
try:
a.append(float(word))
except ValueError:
pass
print(a)
Keluaran:
[1234.0, 56.78]
Untuk menangkap pola yang berbeda, sangat membantu untuk menanyakan dengan pola yang berbeda.
'[\ d] + [., \ d] +'
'[\ d] * [.] [\ d] +'
'[\ d] +'
(Catatan: Prioritaskan pola-pola kompleks terlebih dahulu. Pola-pola sederhana akan mengembalikan potongan tangkapan kompleks alih-alih tangkapan kompleks mengembalikan tangkapan penuh).
p = '[\d]+[.,\d]+|[\d]*[.][\d]+|[\d]+'
Di bawah ini, kami akan mengonfirmasi adanya pola re.search()
, lalu mengembalikan daftar tangkapan yang dapat diubah. Akhirnya, kami akan mencetak setiap tangkapan menggunakan notasi braket untuk men-subseleksi nilai pengembalian objek yang cocok dari objek yang cocok.
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
Pengembalian:
33
42
32
30
444.4
12,001
Karena tidak ada yang berurusan dengan angka keuangan dunia nyata dalam dokumen excel dan word yang perlu saya temukan, inilah variasi saya. Ia menangani int, float, angka negatif, angka mata uang (karena tidak membalas secara terpisah), dan memiliki opsi untuk menjatuhkan bagian desimal dan hanya mengembalikan int, atau mengembalikan semuanya.
Ini juga menangani sistem angka Indian Laks di mana koma muncul secara tidak teratur, tidak setiap 3 angka terpisah.
Itu tidak menangani notasi ilmiah atau angka negatif yang dimasukkan ke dalam tanda kurung dalam anggaran - akan tampak positif.
Itu juga tidak mengekstrak tanggal. Ada cara yang lebih baik untuk menemukan tanggal dalam string.
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, saya menyukai jawaban Anda, tetapi tidak menemukan pelampung. Saya sedang mengerjakan skrip untuk mem-parsing kode menuju pabrik CNC dan perlu menemukan dimensi X dan Y yang bisa bilangan bulat atau mengapung, jadi saya menyesuaikan kode Anda dengan yang berikut. Ini menemukan int, mengapung dengan vals positif dan negatif. Masih tidak menemukan nilai hex berformat tetapi Anda dapat menambahkan "x" dan "A" melalui "F" ke num_char
tuple dan saya pikir itu akan mengurai hal-hal seperti '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)
Pilihan terbaik yang saya temukan di bawah. Ini akan mengekstrak angka dan dapat menghilangkan semua jenis char.
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)
Untuk nomor telepon, Anda cukup mengecualikan semua karakter non-digit dengan \ D di regex:
import re
phone_number = '(619) 459-3635'
phone_number = re.sub(r"\D", "", phone_number)
print(phone_number)