如何在不使用列表的情况下转换字符串中的数字?

时间:2016-10-09 16:53:05

标签: python string python-3.x for-loop

我的教授希望我创建一个函数,该函数返回字符串中的数字总和,但不使用任何列表或列表方法。

操作时该功能应如下所示:

>>> sum_numbers('34 3 542 11')
    590

使用list和list方法时,通常很容易创建这样的函数。但试图在不使用它们的情况下这样做是一场噩梦。

我尝试了以下代码,但他们不能工作:

 >>> def sum_numbers(s):
    for i in range(len(s)):
        int(i)
        total = s[i] + s[i]
        return total


>>> sum_numbers('1 2 3')
'11'

我没有将1,2和3全部转换为整数并加在一起,而是将字符串' 11'换句话说,字符串中的数字仍然没有转换为整数。

我也尝试使用map()函数,但我得到了相同的结果:

>>> def sum_numbers(s):
    for i in range(len(s)):
        map(int, s[i])
        total = s[i] + s[i]
        return total


>>> sum_numbers('1 2 3')
'11'

8 个答案:

答案 0 :(得分:6)

当然完全愚蠢,但为了好玩:

s = '34 3 542 11'

n = ""; total = 0
for c in s:
    if c == " ":
        total = total + int(n)
        n = ""
    else:
        n = n + c
# add the last number
total = total + int(n)

print(total)
> 590

这假设所有字符(除了空格)都是数字。

答案 1 :(得分:2)

你肯定在这里付出了一些努力,但是你的方法的一部分肯定不会按原样运作:你在字符串中迭代字符,但你继续尝试将每个角色视为自己的号码。我编写了一个(非常评论的)方法,可以在不使用任何列表或列表方法的情况下完成您想要的任务:

def sum_numbers(s):
    """
    Convert a string of numbers into a sum of those numbers.

    :param s: A string of numbers, e.g. '1 -2 3.3 4e10'.
    :return: The floating-point sum of the numbers in the string.
    """
    def convert_s_to_val(s):
        """
        Convert a string into a number. Will handle anything that
        Python could convert to a float.

        :param s: A number as a string, e.g. '123' or '8.3e-18'.
        :return: The float value of the string.
        """
        if s:
            return float(s)
        else:
            return 0
    # These will serve as placeholders.
    sum = 0
    current = ''
    # Iterate over the string character by character.
    for c in s:
        # If the character is a space, we convert the current `current`
        # into its numeric representation.
        if c.isspace():
            sum += convert_s_to_val(current)
            current = ''
        # For anything else, we accumulate into `current`.
        else:
            current = current + c
    # Add `current`'s last value to the sum and return.
    sum += convert_s_to_val(current)
    return sum

就个人而言,我会使用这个单行,但它使用str.split()

def sum_numbers(s):
    return sum(map(float, s.split()))

答案 2 :(得分:1)

在这个答案的制作中没有使用(也没有受到伤害)名单:

def sum_string(string):
    total = 0

    if len(string):
        j = string.find(" ") % len(string) + 1
        total += int(string[:j]) + sum_string(string[j:])

    return total

如果字符串比OP指示的更嘈杂,那么这应该更强大:

import re

def sum_string(string):
    pattern = re.compile(r"[-+]?\d+")

    total = 0

    match = pattern.search(string)

    while match:

        total += int(match.group())

        match = pattern.search(string, match.end())

    return total

<强>实施例

>>> sum_string('34 3 542 11')
590
>>> sum_string('   34    4   ')
38
>>> sum_string('lksdjfa34adslkfja4adklfja')
38
>>> # and I threw in signs for fun
... 
>>> sum_string('34 -2 45 -8 13')
82
>>> 

答案 3 :(得分:1)

如果您希望能够处理浮点数和负数:

def sum_numbers(s):
    sm = i = 0
    while i < len(s):
        t = ""
        while  i < len(s) and not s[i].isspace():
            t += s[i]
            i += 1
        if t:
            sm += float(t)
        else:
            i += 1
    return sm

哪种情况适用于所有情况:

In [9]: sum_numbers('34 3 542 11')
Out[9]: 590.0

In [10]: sum_numbers('1.93 -1 23.12 11')
Out[10]: 35.05

In [11]: sum_numbers('')
Out[11]: 0

In [12]: sum_numbers('123456')
Out[12]: 123456.0

或采取切片的变化:

def sum_numbers(s):
    prev = sm = i = 0
    while i < len(s):
        while i < len(s) and not s[i].isspace():
            i += 1
        if i > prev:
            sm += float(s[prev:i])
            prev = i
        i += 1
    return sm

你也可以使用 itertools.groupby ,它不使用任何列表,使用一组允许的字符来分组:

from itertools import groupby


def sum_numbers(s):
    allowed = set("0123456789-.")
    return sum(float("".join(v)) for k,v in groupby(s, key=allowed.__contains__) if k)

为您提供相同的输出:

In [14]: sum_numbers('34 3 542 11')
Out[14]: 590.0

In [15]: sum_numbers('1.93 -1 23.12 11')
Out[15]: 35.05

In [16]: sum_numbers('')
Out[16]: 0

In [17]: sum_numbers('123456')
Out[17]: 123456.0

如果您只需考虑正面整数,可以使用 str.isdigit 作为关键:

def sum_numbers(s):
    return sum(int("".join(v)) for k,v in groupby(s, key=str.isdigit) if k)

答案 4 :(得分:0)

试试这个:

def sum_numbers(s):
    sum = 0
    #This string will represent each number
    number_str = ''
    for i in s:
        if i == ' ':
            #if it is a whitespace it means
            #that we have a number so we incease the sum
            sum += int(number_str)
            number_str = ''
            continue
        number_str += i
    else:
        #add the last number
        sum += int(number_str)
    return sum

答案 5 :(得分:0)

你可以写一个发电机:

def nums(s):
    idx=0
    while idx<len(s):
        ns=''
        while idx<len(s) and s[idx].isdigit():
            ns+=s[idx]
            idx+=1
        yield int(ns)
        while idx<len(s) and not s[idx].isdigit():
            idx+=1

>>> list(nums('34 3 542 11'))
[34, 3, 542, 11]

然后总结一下:

>>> sum(nums('34 3 542 11')) 
590

或者,您可以将re.finditer与正则表达式和生成器构造一起使用:

>>> sum(int(m.group(1)) for m in re.finditer(r'(\d+)', '34 3 542 11'))
590

没有使用名单......

答案 6 :(得分:0)

def sum_numbers(s):
    total=0
    gt=0 #grand total
    l=len(s)
    for i in range(l):
        if(s[i]!=' '):#find each number
            total = int(s[i])+total*10
        if(s[i]==' ' or i==l-1):#adding to the grand total and also add the last number
            gt+=total
            total=0
    return gt

print(sum_numbers('1 2 3'))

此处每个子字符串都会转换为数字并添加到授予总计

答案 7 :(得分:0)

如果我们省略事实evalevil,我们可以用它来解决这个问题。

def sum_numbers(s):
    s = s.replace(' ', '+')
    return eval(s)

是的,那很简单。但我不会把这件事投入生产。

确定我们需要测试一下:

from hypothesis import given
import hypothesis.strategies as st


@given(list_num=st.lists(st.integers(), min_size=1))
def test_that_thing(list_num):
    assert sum_numbers(' '.join(str(i) for i in list_num)) == sum(list_num)

test_that_thing()

它什么也不提。