How to convert numbers in a string without using lists?
<p>My prof wants me to create a function that return the sum of numbers in a string but without using any lists or list methods.</p>

<p>The function should look like this when operating:</p>

<pre><code>&gt;&gt;&gt; sum_numbers('34 3 542 11')
    590
</code></pre>

<p>Usually a function like this would be easy to create when using lists and list methods. But trying to do so without using them is a nightmare.</p>

<p>I tried the following code but they don't work:</p>

<pre><code> &gt;&gt;&gt; def sum_numbers(s):
    for i in range(len(s)):
        int(i)
        total = s[i] + s[i]
        return total


&gt;&gt;&gt; sum_numbers('1 2 3')
'11'
</code></pre>

<p>Instead of getting 1, 2, and 3 all converted into integers and added together, I instead get the string '11'. In other words, the numbers in the string still have not been converted to integers.</p>

<p>I also tried using a <code>map()</code> function but I just got the same results:</p>

<pre><code>&gt;&gt;&gt; def sum_numbers(s):
    for i in range(len(s)):
        map(int, s[i])
        total = s[i] + s[i]
        return total


&gt;&gt;&gt; sum_numbers('1 2 3')
'11'
</code></pre>

<p>If you want to be able to handle floats and negative numbers:</p>

<pre><code>def sum_numbers(s):
    sm = i = 0
    while i &lt; len(s):
        t = ""
        while  i &lt; len(s) and not s[i].isspace():
            t += s[i]
            i += 1
        if t:
            sm += float(t)
        else:
            i += 1
    return sm
</code></pre>

<p>Which will work for all cases:</p>

<pre><code>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
</code></pre>

<p>Or a variation taking slices:</p>

<pre><code>def sum_numbers(s):
    prev = sm = i = 0
    while i &lt; len(s):
        while i &lt; len(s) and not s[i].isspace():
            i += 1
        if i &gt; prev:
            sm += float(s[prev:i])
            prev = i
        i += 1
    return sm
</code></pre>

<p>You could also use <em>itertools.groupby</em> which uses no lists, using a set of allowed chars to group by:</p>

<pre><code>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)
</code></pre>

<p>which gives you the same output:</p>

<pre><code>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
</code></pre>

<p>Which if you only have to consider positive ints could just use <em>str.isdigit</em> as the key:</p>

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

python string python-3.x for-loop