Відповіді:
Якщо ви бажаєте витягнути лише додатні цілі числа, спробуйте наступне:
>>> str = "h3110 23 cat 444.4 rabbit 11 2 dog"
>>> [int(s) for s in str.split() if s.isdigit()]
[23, 11, 2]
Я б заперечував, що це краще, ніж приклад регулярного вираження з трьох причин. По-перше, вам не потрібен інший модуль; по-друге, це читабельніше, оскільки вам не потрібно розбирати міні-мову регулярних виразів; по-третє, це швидше (і, ймовірно, більш пітонічно):
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
Це не розпізнає плавці, від’ємні цілі числа чи цілі числа у шістнадцятковому форматі. Якщо ви не можете прийняти ці обмеження, тонка відповідь подана нижче, зробить свою справу.
re
. Це загальний і потужний інструмент (тому ви дізнаєтесь щось дуже корисне). Швидкість дещо не має значення при аналізі журналу (зрештою, це не якийсь інтенсивний чисельний вирішувач), re
модуль знаходиться у стандартній бібліотеці Python, і завантажувати його не завадить.
mumblejumble45mumblejumble
в яких я знав, що є лише одне число. Рішення просто int(filter(str.isdigit, your_string))
.
str
яка потім переосмислює str
об'єкт і метод в базовому пітоні. Це не є хорошою практикою, оскільки вам це може знадобитися пізніше в сценарії.
int(filter(...))
підніме TypeError: int() argument must be a string...
для Python 3.5, тому ви можете використовувати оновлену версію: int(''.join(filter(str.isdigit, your_string)))
для вилучення всіх цифр до одного цілого числа.
Я б використовував регулярний вираз:
>>> import re
>>> re.findall(r'\d+', 'hello 42 I\'m a 32 string 30')
['42', '32', '30']
Це також відповідатиме 42 с bla42bla
. Якщо ви хочете лише цифри, обмежені межами слова (пробіл, період, кома), ви можете використовувати \ b:
>>> re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string 30')
['42', '32', '30']
На закінчення зі списком чисел замість списку рядків:
>>> [int(s) for s in re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string 30')]
[42, 32, 30]
int
на нього карту, і ви закінчите. +1 особливо для останньої частини. Я б хотів запропонувати сирі рядки ( r'\b\d+\b' == '\\b\\d+\\b'
).
int_list = [int(s) for s in re.findall('\\d+', 'hello 12 hi 89')]
map
.
Це більш ніж пізно, але ви можете розширити вираз регулярного вираження, щоб врахувати і наукові позначення.
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)
Все добре дає!
Крім того, ви можете подивитися вбудований регулярний вираз AWS Glue
s = "4"
повернення не відповідає. Чи можна редагувати, щоб також про це піклуватися?
[+-]?\d*[\.]?\d*(?:(?:[eE])[+-]?\d+)?
Ця група дає деякі помилкові позитиви (тобто +
захоплюється сама часом), але здатна обробляти більше форм, наприклад .001
, плюс вона не поєднує числа автоматично (як у s=2+1
)
[-+]?[.]?[\d]+(?:,\d\d\d)*[\.]?\d*(?:[eE][-+]?\d+)?
- такий дурний мене ... як я не міг про це думати?
Я припускаю, що ви хочете, щоб плаває не просто цілі числа, тому я б зробив щось подібне:
l = []
for t in s.split():
try:
l.append(float(t))
except ValueError:
pass
Зауважте, що деякі інші рішення, розміщені тут, не працюють з негативними цифрами:
>>> re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string -30')
['42', '32', '30']
>>> '-3'.isdigit()
False
float
на int
.
re.findall("[-\d]+", "1 -2")
continue
замість pass
цього циклу?
Якщо ви знаєте, що це буде лише одне число в рядку, тобто "привіт 12 привіт", ви можете спробувати фільтрувати.
Наприклад:
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
Але будьте обережні !!! :
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'
- виправлення за допомогоюint("".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]
Використання Regex нижче - це спосіб
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
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*')
має бути: 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'
line2 = "hello 12 hi 89"
temp1 = re.findall(r'\d+', line2) # through regular expression
res2 = list(map(int, temp1))
print(res2)
Привіт ,
ви можете шукати всі цілі числа в рядку через цифру, використовуючи вираз findall.
На другому кроці створіть список res2 та додайте до цього списку цифри, знайдені в рядку
сподіваюся, що це допомагає
З повагою, Дівакар Шарма
Ця відповідь також містить випадок, коли число є плаваючою в рядку
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)
Я вражений тим, що ніхто ще не згадав про використання itertools.groupby
як альтернативу для досягнення цього.
Ви можете використовувати itertools.groupby()
разом із 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]
Затримане значення l
буде:
[12, 89]
PS: Це просто задля ілюстрації, щоб показати, що як альтернативу ми також можемо використовуватись groupby
для досягнення цього. Але це не рекомендується рішення. Якщо ви хочете досягти цього, вам слід використовувати прийняту відповідь fmark, засновану на розумінні списку з str.isdigit
фільтром.
Я просто додаю цю відповідь, тому що ніхто не додав жодної, використовуючи обробку Exception, і тому що це також працює для плаваючих елементів
a = []
line = "abcd 1234 efgh 56.78 ij"
for word in line.split():
try:
a.append(float(word))
except ValueError:
pass
print(a)
Вихід:
[1234.0, 56.78]
Для лову різних моделей корисно проводити запит з різними шаблонами.
'[\ d] + [., \ d] +'
'[\ d] * [.] [\ d] +'
'[\ d] +'
(Примітка. Поставте спочатку складні візерунки. Ще прості візерунки повернуть шматочки складного улову замість складного вилову, який повертає повний вилов).
p = '[\d]+[.,\d]+|[\d]*[.][\d]+|[\d]+'
Нижче ми підтвердимо, що шаблон присутній re.search()
, а потім повернемо ітерабельний список уловів. Нарешті, ми надрукуємо кожен улов, використовуючи позначення дужок, щоб підсележувати значення об'єкта відповідності від об'єкта відповідності.
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
Повернення:
33
42
32
30
444.4
12,001
Оскільки жоден із них не стосувався реальних фінансових цифр у програмах excel та word, які мені потрібно було знайти, ось моя зміна. Він обробляє вставки, поплавці, негативні числа, валютні номери (оскільки він не відповідає розділенням) і має можливість скинути десяткову частину і просто повернути вставки або повернути все.
Він також обробляє систему числення Indian Laks, де коми з’являються нерегулярно, а не кожні 3 числа.
Це не обробляє наукові позначення або негативні цифри, що містяться в дужках у бюджетах - виявляться позитивними.
Він також не витягує дати. Є кращі способи пошуку дат у рядках.
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, мені сподобалась ваша відповідь, але вона не знайшла поплавців. Я працюю над сценарієм для розбору коду, що надходить до фрези з ЧПУ, і мені потрібно було знайти розміри X і Y, які можуть бути цілими чи плаваючими, тому я адаптував ваш код до наступного. Це знаходить int, float з позитивними та негативними vals. Досі не знаходять значень у форматі шістнадцяткових значень, але ви можете додати "x" та "A" через "F" до num_char
кортежу, і я думаю, що це би розібрало такі речі, як "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)
Найкращий варіант, який я знайшов, наведений нижче. Це витягне число і може усунути будь-який тип знаків.
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)
Для телефонних номерів можна просто виключити всі нецифрові символи з \ D у регулярному виразі:
import re
phone_number = '(619) 459-3635'
phone_number = re.sub(r"\D", "", phone_number)
print(phone_number)