在Python中从字符串中提取数字

65
我有一个字符串,我想从中提取数字。例如:
str1 = "3158 reviews"
print (re.findall('\d+', str1 ))

输出是['4', '3'] 我只想得到3158,最好是作为整数,而不是作为列表。

14
你的代码输出结果是 ['3158'] - 101
9
那么你一定没有运行上面显示的代码! - 101
1
你的输出中有4但输入中没有,这说明你可能漏了其它东西。正则表达式应该没问题。 - AsheKetchum
5
看到这个问题已经过去3年了,让我感到开心。我因为一个愚蠢的问题得到了很多赞,是的,我运行了错误的代码,但当时我没有时间在评论中说明。 - Umair Ayub
2
你运行了什么代码? - BAC83
18个回答

113
您可以使用 str.isdigit 方法来过滤字符串中的数字
>>> int(filter(str.isdigit, str1))
3158

对于Python3:

int(list(filter(str.isdigit, my_str))[0])

49
似乎不适用于Python 3,可能是因为在Python 3中filter是一个类,像你这样调用它会返回一个可迭代的filter对象,而int()不能将filter对象转换为int。在我看来,在Python 3中没有优雅的方式(比如你的答案中没有使用正则表达式)来完成这个任务。有吗? - Ray
13
@Ray,我来晚了,但我猜其他人可能也会遇到同样的问题。例如,你可以使用int(list(filter(str.isdigit, my_str))[0])。如果filter返回一个可迭代对象,你只需要使用它就行了 :) - JChris
15
补充Juan的评论:如果你想获取字符串中的所有数字而不仅仅是第一个数字,可以使用int(''.join(list(filter(str.isdigit, my_str)))) - apricity
29
不需要使用列表:int(''.join(filter(str.isdigit, 'test3246'))) 该代码的作用是从字符串中提取数字,然后将其转换为整数。 - uzumaki
3
我不确定这个解决方案是否适用于数字提取的一般情况。考虑在“3158 reviews 3158asdf 4”上使用它。 - AsheKetchum
显示剩余4条评论

41

这段代码可以正常工作。肯定存在其他问题:

>>> import re
>>> str1 = "3158 reviews"
>>> print (re.findall('\d+', str1 ))
['3158']

3
这是一个列表吗?因为问题说,我不想要一个列表。 - mLstudent33

23
IntVar = int("".join(filter(str.isdigit, StringVar)))

5
与被接受的答案不同,这适用于Python3。 - Adrian W
3
正是问题上方的标签所指出的。#python-3.x - Bernard

20

你的正则表达式看起来正确。你确定你没有在变量名上犯错误吗? 在你上面的代码中,你混淆了 total_hotel_reviews_stringstr

>>> import re
>>> s = "3158 reviews"
>>> 
>>> print(re.findall("\d+", s))
['3158']

8
您离最终答案已经非常接近了。您的re.findall表达式只需要添加括号以捕获所有检测到的数字即可:

re.findall('(\d+)', str1)

对于更一般的字符串,例如str1 = "3158 reviews, 432 users",此代码将产生以下结果:

输出:['3158','432']

现在,为了获取整数,您可以使用map函数将int函数映射到字符串中进行转换:

A = list(map(int,re.findall('(\d+)',str1)))

或者,您可以使用这个单行循环:

A = [ int(x) for x in re.findall('(\d+)',str1) ]

这两种方法都是正确的。它们都产生A = [3158, 432]
原始问题的最终result将是数组A中的第一个条目,因此我们得出以下任意一个表达式:

result = list(map(int,re.findall('(\d+)', str1)))[0]

result = int(re.findall('(\d+)', str1)[0])

即使str1中只有一个数字,re.findall仍将返回一个列表,因此您需要手动检索第一个元素A[0]

7
为了从一个字符串中提取单个数字,您可以使用 re.search(),它返回第一个匹配项(或None):
>>> import re
>>> string = '3158 reviews'
>>> int(re.search(r'\d+', string).group(0))
3158

在Python 3.6+中,您还可以索引匹配对象,而不是使用group()

>>> int(re.search(r'\d+', string)[0])
3158

这只能在Python2中工作,还是可以在Python2和Python3中都工作? - Matheus Francisco
@Matheus 此外,re 模块在 1.5 及更高版本中可用 :) - Eugene Yarmash
1
通用编码解决方案适用于Python 2和3,是使用.findall方法而非.search 方法。.findall方法总是返回一个包含string项的列表。该列表将包含所有找到的值,因此需要一个索引。例如,可以将最后一项作为从后面检索的最后一个索引进行处理:int(re.findall(r'\d+', string)[-1]) - s3n0

6

Python 2.7:

>>> str1 = "3158 reviews"
>>> int(filter(str.isdigit, str1))
3158

Python 3:

>>> str1 = "3158 reviews"
>>> int(''.join(filter(str.isdigit, str1)))
3158

目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community

6
如果格式很简单(数字和其他内容之间用空格分隔),那么:
int(str1.split()[0])

我愿意做这件事


如果格式如此简单,太好了...我传递了一个错误的变量...顺便说一下...你告诉我了一个最短的解决方案...谢谢。 - Umair Ayub
很好,但只有在数字后面有空格的情况下才有效,例如对于str1 =“3158 reviews”,而不是对于str1 =“3158reviews”。 - jacanterbury

5

适用于各种复杂类型

str1 = "sg-23.0 300sdf343fc  -34rrf-3.4r" #All kinds of occurrence of numbers between strings
num = [float(s) for s in re.findall(r'-?\d+\.?\d*', str1)]
print(num)

输出:
[-23.0, 300.0, 343.0, -34.0, -3.4]

3
上述解决方案似乎假定为整数。这里有一个小修改,允许使用小数:
num = float("".join(filter(lambda d: str.isdigit(d) or d == '.', inputString)

(不考虑负号,并假设任何小数点都正确放置在数字字符串中,而不仅仅是一些英语语言的句点。它不是为了不可磨灭而建立的,但对于我的数据情况有效。)

喜欢它。一种特定问题类的超级简单解决方案。 - Colin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接