4

在我尝试编写的函数中,用户输入了一堆数字,例如“648392”。我把这个字符串变成这样的列表:['6', '4', '8', '3', '9', '2']。

我希望能够对这些数字求和,所以我将列表中的数字转换为整数而不是字符串。这一切都很好,但是我也希望用户能够输入字母,然后我会将它们从列表中删除 - 这就是我卡住的地方。例如,用户输入“6483A2”。

我无法使用 isDigit 检查元素是否为数字,因为这些元素显然必须首先是整数,而且我无法将列表中的元素转换为整数,因为其中一些元素是字母......我'我确定有一个简单的解决方案,但我在 python 方面非常糟糕,所以任何帮助将不胜感激!

4

7 回答 7

6

您可以使用str.translate过滤掉字母:

>>> from string import letters
>>> strs = "6483A2"
>>> strs.translate(None, letters)
'64832'

无需将字符串转换为列表,您可以遍历字符串本身。

使用str.join,str.isdigit和列表理解:

>>> ''.join([c for c in strs if c.isdigit()])
'64832'

或者这个你想要的sum数字:

sum(int(c) for c in strs if c.isdigit())

时间比较:

小字符串:

>>> strs = "6483A2"
>>> %timeit sum(int(c) for c in strs.translate(None, letters))
100000 loops, best of 3: 9.19 us per loop
>>> %timeit sum(int(c) for c in strs if c.isdigit())
100000 loops, best of 3: 10.1 us per loop

大字符串:

>>> strs = "6483A2"*1000
>>> %timeit sum(int(c) for c in strs.translate(None, letters))
100 loops, best of 3: 5.47 ms per loop
>>> %timeit sum(int(c) for c in strs if c.isdigit())
100 loops, best of 3: 8.54 ms per loop

最坏情况,所有字母:

>>> strs = "A"*100
>>> %timeit sum(int(c) for c in strs.translate(None, letters))
100000 loops, best of 3: 2.53 us per loop
>>> %timeit sum(int(c) for c in strs if c.isdigit())
10000 loops, best of 3: 24.8 us per loop
>>> strs = "A"*1000
>>> %timeit sum(int(c) for c in strs.translate(None, letters))
100000 loops, best of 3: 7.34 us per loop
>>> %timeit sum(int(c) for c in strs if c.isdigit())
1000 loops, best of 3: 210 us per loop
于 2013-08-08T00:58:58.567 回答
3

filter您可以使用函数或理解从任何可迭代(包括字符串)中过滤掉事物。例如,以下任一:

digits = filter(str.isdigit, input_string)
digits = (character for character in input_string if character.isdigit())

…会给你一个可迭代的充满数字的。如果您想将每个转换为数字,以下任何一种都可以:

numbers = map(int, filter(str.isdigit, input_string))
numbers = (int(character) for character in input_string if character.isdigit())

因此,要获得所有数字的总和,跳过字母,只需将其中任何一个传递给sum函数:

total = sum(map(int, filter(str.isdigit, input_string)))
total = sum(int(character) for character in input_string if character.isdigit())

从你的最后一段:

我无法使用 isDigit 检查元素是否为数字,因为元素显然必须首先是整数,而且我无法将列表中的元素转换为整数

首先,是isdigit,不是isDigit。其次,isdigit是一个字符串方法,而不是整数,所以你错误地认为你不能在字符串上调用它。事实上,在将字符串转换为整数之前,您必须在字符串上调用它。

但这确实带来了另一种选择。在 Python 中,Ask Forgiveness 通常比 Permission 更容易。与其弄清楚是否可以将每个字母转换为 int,然后再去做,我们可以尝试将其转换为 int,然后处理可能的失败。例如:

def get_numbers(input_string):
    for character in input_string:
        try:
            yield int(character)
        except TypeError:
            pass

现在,它只是:

total = sum(get_numbers(input_string))
于 2013-08-08T01:00:33.850 回答
2

您可以通过理解来做到这一点:

>>> s = "6483A2"
>>> [int(c) for c in s if c.isdigit()]
[6, 4, 8, 3, 2]
>>> sum(int(c) for c in s if c.isdigit())
23

如果您想直接从混合字符串转到仅包含整数的列表,这种方法很好,这大概是您的目标。

于 2013-08-08T01:00:45.043 回答
1
>>> a = "hello123987io"
>>> b = "khj7djksh787"
>>> sum([int(letter) for letter in b if letter.isdigit()])
29
>>> sum([int(letter) for letter in a if letter.isdigit()])
30

>>> def getInputAndSum(userInput):
...     """ returns a tuple with the input string and its sum """
...     return userInput, sum([int(letter) for letter in userInput if letter.isdigit()])
... 
>>> getInputAndSum("Th1s1550mesum")
('Th1s1550mesum', 12)
于 2013-08-08T01:02:02.867 回答
1

您可以使用生成器表达式并将其放在sum.

>>> import string
>>> s
'6483A2'
>>> sum(int(x) for x in list(s) if x in string.digits)
23

如果没有其他模块要导入,请使用isdigit

sum(int(x) for x in list(s) if x.isdigit())
于 2013-08-08T01:00:46.910 回答
1

只是贡献一点,如果你想要总和,你可以这样做:

x = "6483A2"
sum(map(int, filter(str.isdigit, x)))
>>>23

如果您仅出于其他目的或其他目的需要整数列表,sum则只需将其保留在map

map(int, filter(str.isdigit, x))
>>>[6, 4, 8, 3, 2]

注意:关于string.letters方法。letterslocale依赖的,所以这个:

import locale, string
locale.setlocale(locale.LC_ALL, 'es_ES') # or 'esp_esp' if you're on Windows
string.letters
>>> "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzŠŚŽšśžźŞµşŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőöřůúűüýţ˙"

尽管我会regex按照上面的建议推荐这种情况:)

很高兴合作:D

于 2013-08-08T01:15:03.307 回答
0

虽然确实可以通过各种方式过滤掉字母,但让解释器决定什么可以解释为数字,什么不能解释可能更符合 Pythonic。因此,即使它不是单行的,您也可能更喜欢这种方法:

aninput = "648392A0&sle4"
def discard_non_ints(itbl, rdx=10):
  for d in itbl:
    try:
      yield(int(d, rdx))
    except ValueError:
      pass

sum(discard_non_ints(aninput))
36

这种方法特别好的地方在于它使您可以灵活地包含非十进制数字。想要对所有十六进制数字求和?

sum(discard_non_ints('deadbeforenoon', 16))
104
于 2013-08-08T01:15:00.480 回答