Yanıtlar:
Yalnızca pozitif tamsayıları ayıklamak istiyorsanız, aşağıdakileri deneyin:
>>> str = "h3110 23 cat 444.4 rabbit 11 2 dog"
>>> [int(s) for s in str.split() if s.isdigit()]
[23, 11, 2]
Bunun üç nedenden dolayı normal ifade örneğinden daha iyi olduğunu iddia ediyorum. İlk olarak, başka bir modüle ihtiyacınız yoktur; ikincisi, daha okunaklıdır çünkü regex mini dilini ayrıştırmanıza gerek yoktur; ve üçüncüsü, daha hızlıdır (ve muhtemelen daha fazla pitoniktir):
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
Bu, kayan sayıları, negatif tam sayıları veya onaltılık biçimde tam sayıları tanımaz. Bu sınırlamaları kabul edemezseniz, slim'un aşağıdaki cevabı işe yarayacaktır.
re
. Genel ve güçlü bir araçtır (bu yüzden çok faydalı bir şey öğrenirsiniz). Günlük ayrıştırma işleminde hız biraz önemsizdir (sonuçta bazı yoğun sayısal çözücü değildir), re
modül standart Python kitaplığındadır ve yüklemek zarar vermez.
mumblejumble45mumblejumble
sadece bir sayı olduğunu bildiğim dizeler vardı . Çözüm basittir int(filter(str.isdigit, your_string))
.
str
geçersiz kılan değişkeni tanımlarsınız str
. Bu daha iyi bir uygulama değildir çünkü senaryoda daha sonra ihtiyacınız olabilir.
int(filter(...))
TypeError: int() argument must be a string...
Python 3.5 için yükselecektir , böylece güncellenmiş sürümü kullanabilirsiniz: int(''.join(filter(str.isdigit, your_string)))
tüm basamakları tek bir tamsayıya çıkarmak için.
Bir normal ifade kullanırdım:
>>> import re
>>> re.findall(r'\d+', 'hello 42 I\'m a 32 string 30')
['42', '32', '30']
Bu aynı zamanda şuradan 42 eşleşir bla42bla
. Yalnızca kelime sınırlarıyla (boşluk, nokta, virgül) ayrılmış sayılar istiyorsanız \ b:
>>> re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string 30')
['42', '32', '30']
Dizeler listesi yerine bir sayı listesi bulmak için:
>>> [int(s) for s in re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string 30')]
[42, 32, 30]
int
çizdiğinizde işleminiz tamamlanmış demektir. Özellikle ikinci kısım için +1. Ham dizeleri ( r'\b\d+\b' == '\\b\\d+\\b'
) olsa öneririz .
int_list = [int(s) for s in re.findall('\\d+', 'hello 12 hi 89')]
map
.
Bu biraz geç oldu, ancak bilimsel ifadeyi de hesaba katmak için normal ifade ifadesini genişletebilirsiniz.
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)
Her şeyi verir!
Ayrıca, AWS Glue yerleşik regex'e de bakabilirsiniz.
s = "4"
eşleşme döndürmez. Bununla ilgilenmek için yeniden düzenlenebilir mi?
[+-]?\d*[\.]?\d*(?:(?:[eE])[+-]?\d+)?
Bu grup bazı yanlış pozitifler verir (yani +
bazen kendi başına yakalanır), ancak daha fazla formu işleyebilir, örneğin .001
, sayıları otomatik olarak birleştirmez (olduğu gibi s=2+1
)
[-+]?[.]?[\d]+(?:,\d\d\d)*[\.]?\d*(?:[eE][-+]?\d+)?
- çok aptalca ... bunu nasıl düşünemedim?
Ben sadece tamsayılar şamandıralar istediğiniz varsayıyorum bu yüzden böyle bir şey yapmak istiyorum:
l = []
for t in s.split():
try:
l.append(float(t))
except ValueError:
pass
Burada yayınlanan diğer çözümlerin bazılarının negatif sayılarla çalışmadığını unutmayın:
>>> re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string -30')
['42', '32', '30']
>>> '-3'.isdigit()
False
float
için int
.
re.findall("[-\d]+", "1 -2")
continue
yerine yazarsak herhangi bir fark yaratır mı pass
?
Dizede yalnızca bir sayı olacağını biliyorsanız, yani 'merhaba 12 merhaba', filtreyi deneyebilirsiniz.
Örneğin:
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
Ama dikkatli olun !!! :
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'
- kullanarak sabitlemeint("".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]
Aşağıdaki Regex'i kullanmak
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)
findall ile
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*')
olması gereken: repl_str = re.compile('\d+\.?\d*')
python3.7 re.search(re.compile(r'\d+.?\d*'), "42G").group()
'42G' re.search(re.compile(r'\d+\.?\d*'), "42G").group()
'42' kullanarak tekrarlanabilir bir örnek için
line2 = "hello 12 hi 89"
temp1 = re.findall(r'\d+', line2) # through regular expression
res2 = list(map(int, temp1))
print(res2)
Selam ,
findall ifadesini kullanarak dizedeki tüm tamsayıları basamaktan arayabilirsiniz.
İkinci adımda res2 listesi oluşturun ve dizede bulunan rakamları bu listeye ekleyin
Bu yardımcı olur umarım
Saygılarımızla, Diwakar Sharma
Bu yanıt ayrıca, sayı dizede kayar durumdayken de bulunur
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)
Bunu itertools.groupby
başarmak için henüz kimsenin kullanımından bahsetmediğini görmek beni şaşırttı .
Dizeden sayıları aşağıdaki gibi ayıklamak için itertools.groupby()
birlikte kullanabilirsiniz str.isdigit()
:
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]
Bekletme değeri l
:
[12, 89]
Not: Bu sadece gösterim amacıyla, alternatif olarak bunu groupby
başarmak için de kullanabileceğimizi göstermek içindir. Ancak bu önerilen bir çözüm değildir. Bunu başarmak istiyorsanız, liste kavrayışı filtre olarak kullanmaya dayalı olarak fmark'ın kabul edilen cevabını kullanmalısınız str.isdigit
.
Ben sadece bu yanıtı ekliyorum çünkü kimse Exception işlemeyi kullanarak bir tane eklemedi ve bu aynı zamanda şamandıralar için de çalışıyor
a = []
line = "abcd 1234 efgh 56.78 ij"
for word in line.split():
try:
a.append(float(word))
except ValueError:
pass
print(a)
Çıktı :
[1234.0, 56.78]
Farklı desenleri yakalamak için farklı desenlerle sorgulamak faydalıdır.
[\ D] + [. \ D] + '
[\ D] * [.] [\ D] + '
[\ D] + '
(Not: Önce karmaşık kalıpları koyun, basit kalıplar tam yakalamayı döndüren karmaşık yakalama yerine karmaşık yakalamanın parçalarını döndürür).
p = '[\d]+[.,\d]+|[\d]*[.][\d]+|[\d]+'
Aşağıda, bir desenin bulunduğunu onaylayacağız re.search()
, ardından tekrarlanabilir bir yakalama listesi döndüreceğiz. Son olarak, her bir yakalamayı, eşleme nesnesinden eşleme nesnesi dönüş değerini alt seçmek için köşeli ayraç gösterimini kullanarak yazdıracağız.
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
İadeler:
33
42
32
30
444.4
12,001
Bunların hiçbiri, bulmam gereken excel ve word belgelerindeki gerçek dünya finansal rakamlarıyla ilgilenmediğinden, işte benim varyasyonum. Ints, float, negatif sayılar, para birimi numaralarını (bölünmüş olarak yanıt vermediği için) işler ve ondalık kısmı bırakıp sadece iade veya her şeyi iade etme seçeneğine sahiptir.
Ayrıca virgüllerin düzensiz bir şekilde göründüğü Indian Laks sayı sistemini yönetir, her 3 rakamdan ayrı değildir.
Bütçe içindeki parantez içine konulan bilimsel gösterimi veya negatif sayıları ele almaz - olumlu görünecektir.
Ayrıca tarihleri ayıklamaz. Dizelerde tarih bulmanın daha iyi yolları vardır.
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, cevabınızı beğendim, ama yüzer bulmadı. Ben bir CNC değirmen gidiyor kod ayrıştırmak için bir komut dosyası üzerinde çalışıyorum ve tamsayı veya kayan olabilir hem X ve Y boyutları bulmak için gerekli, bu yüzden aşağıdaki kod uyarlanmış. Bu pozitif ve negatif değerlerle int, float bulur. Hala onaltılık biçimlendirilmiş değerler bulamıyor ancak "x" ve "A" ile "F" ile num_char
tuple ekleyebilirsiniz ve ben '0x23AC' gibi şeyleri ayrıştıracağını düşünüyorum.
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)
Bulduğum en iyi seçenek aşağıda. Bir sayı çıkarır ve herhangi bir karakter türünü ortadan kaldırabilir.
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)
Telefon numaraları için, regex'te \ D olan rakam olmayan tüm karakterleri hariç tutabilirsiniz:
import re
phone_number = '(619) 459-3635'
phone_number = re.sub(r"\D", "", phone_number)
print(phone_number)