Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #83556 > unrolled thread

extracting numbers with decimal places from a string

Started byStore Makhzan <store0a@gmail.com>
First post2015-01-11 11:31 -0800
Last post2015-01-12 12:13 +1100
Articles 19 — 9 participants

Back to article view | Back to comp.lang.python


Contents

  extracting numbers with decimal places from a string Store Makhzan <store0a@gmail.com> - 2015-01-11 11:31 -0800
    Re: extracting numbers with decimal places from a string Joel Goldstick <joel.goldstick@gmail.com> - 2015-01-11 15:06 -0500
      Re: extracting numbers with decimal places from a string Store Makhzan <store0a@gmail.com> - 2015-01-11 12:26 -0800
        Re: extracting numbers with decimal places from a string Joel Goldstick <joel.goldstick@gmail.com> - 2015-01-11 16:42 -0500
          Re: extracting numbers with decimal places from a string Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-01-11 23:20 +0100
            Re: extracting numbers with decimal places from a string Joel Goldstick <joel.goldstick@gmail.com> - 2015-01-11 17:54 -0500
              Re: extracting numbers with decimal places from a string Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-01-12 00:12 +0100
                Re: extracting numbers with decimal places from a string Joel Goldstick <joel.goldstick@gmail.com> - 2015-01-11 18:35 -0500
                  Re: extracting numbers with decimal places from a string Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-01-12 00:46 +0100
                    Re: extracting numbers with decimal places from a string Peter Otten <__peter__@web.de> - 2015-01-12 01:09 +0100
                      Re: extracting numbers with decimal places from a string Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-01-12 01:45 +0100
                    Re: extracting numbers with decimal places from a string Chris Angelico <rosuav@gmail.com> - 2015-01-12 11:17 +1100
            Re: extracting numbers with decimal places from a string Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-01-12 11:45 +1100
          Re: extracting numbers with decimal places from a string Grant Edwards <invalid@invalid.invalid> - 2015-01-11 23:06 +0000
    Re: extracting numbers with decimal places from a string Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-01-12 00:07 +0100
      Re: extracting numbers with decimal places from a string Mark Lawrence <breamoreboy@yahoo.co.uk> - 2015-01-12 00:04 +0000
        Re: extracting numbers with decimal places from a string Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-01-12 02:00 +0100
      Re: extracting numbers with decimal places from a string MRAB <python@mrabarnett.plus.com> - 2015-01-12 00:59 +0000
      Re: extracting numbers with decimal places from a string Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-01-12 12:13 +1100

#83556 — extracting numbers with decimal places from a string

FromStore Makhzan <store0a@gmail.com>
Date2015-01-11 11:31 -0800
Subjectextracting numbers with decimal places from a string
Message-ID<7240a574-dfd7-46c3-80eb-0657b41894bb@googlegroups.com>
I have this script which can calculate the total of numbers given in a string
---- script -----
total = 0
for c in '0123456789':
   total += int(c)
print total
---- script -----

How should I modify this script to find the total of if the numbers given in the string form have decimal places? That is, how do I need to modify this line:
----- script -----
for c in '1.32, 5.32, 4.4, 3.78':
----- script -----
to find the total of these given numbers.

[toc] | [next] | [standalone]


#83559

FromJoel Goldstick <joel.goldstick@gmail.com>
Date2015-01-11 15:06 -0500
Message-ID<mailman.17591.1421006803.18130.python-list@python.org>
In reply to#83556
On Sun, Jan 11, 2015 at 2:31 PM, Store Makhzan <store0a@gmail.com> wrote:
> I have this script which can calculate the total of numbers given in a string
> ---- script -----
> total = 0
> for c in '0123456789':
>    total += int(c)
> print total
> ---- script -----
>
> How should I modify this script to find the total of if the numbers given in the string form have decimal places? That is, how do I need to modify this line:
> ----- script -----
> for c in '1.32, 5.32, 4.4, 3.78':
> ----- script -----
> to find the total of these given numbers.
> --
> https://mail.python.org/mailman/listinfo/python-list

split the string on ',' to get a list of strings.  loop thru list
using float(s), add float values


-- 
Joel Goldstick
http://joelgoldstick.com

[toc] | [prev] | [next] | [standalone]


#83562

FromStore Makhzan <store0a@gmail.com>
Date2015-01-11 12:26 -0800
Message-ID<3bfeea22-cded-4363-92fa-6f1b33ddae16@googlegroups.com>
In reply to#83559
On Sunday, January 11, 2015 at 2:06:54 PM UTC-6, Joel Goldstick wrote:
> On Sun, Jan 11, 2015 at 2:31 PM, Store Makhzan wrote:
> > I have this script which can calculate the total of numbers given in a string
> > ---- script -----
> > total = 0
> > for c in '0123456789':
> >    total += int(c)
> > print total
> > ---- script -----
> >
> > How should I modify this script to find the total of if the numbers given in the string form have decimal places? That is, how do I need to modify this line:
> > ----- script -----
> > for c in '1.32, 5.32, 4.4, 3.78':
> > ----- script -----
> > to find the total of these given numbers.
> > --
> > https://mail.python.org/mailman/listinfo/python-list
> 
> split the string on ',' to get a list of strings.  loop thru list
> using float(s), add float values
> 
> 
> -- 
> Joel Goldstick
> http://joelgoldstick.com

Thank you
Here is what I did:

----- script -----
#Check if a perfect cube
total = 0
for c in ('1.23', '2.4', '3.123'):
   print float(c)
   total += float(c)
print total
----- script -----

Which gave me the result I wanted.
Since I am new to Python, I used () as a guess, and it worked.

[toc] | [prev] | [next] | [standalone]


#83566

FromJoel Goldstick <joel.goldstick@gmail.com>
Date2015-01-11 16:42 -0500
Message-ID<mailman.17595.1421012580.18130.python-list@python.org>
In reply to#83562
On Sun, Jan 11, 2015 at 3:26 PM, Store Makhzan <store0a@gmail.com> wrote:
> On Sunday, January 11, 2015 at 2:06:54 PM UTC-6, Joel Goldstick wrote:
>> On Sun, Jan 11, 2015 at 2:31 PM, Store Makhzan wrote:
>> > I have this script which can calculate the total of numbers given in a string
>> > ---- script -----
>> > total = 0
>> > for c in '0123456789':
>> >    total += int(c)
>> > print total
>> > ---- script -----
>> >
>> > How should I modify this script to find the total of if the numbers given in the string form have decimal places? That is, how do I need to modify this line:
>> > ----- script -----
>> > for c in '1.32, 5.32, 4.4, 3.78':
>> > ----- script -----
>> > to find the total of these given numbers.
>> > --
>> > https://mail.python.org/mailman/listinfo/python-list
>>
>> split the string on ',' to get a list of strings.  loop thru list
>> using float(s), add float values
>>
>>
>> --
>> Joel Goldstick
>> http://joelgoldstick.com
>
> Thank you
> Here is what I did:
>
> ----- script -----
> #Check if a perfect cube
> total = 0
> for c in ('1.23', '2.4', '3.123'):
>    print float(c)
>    total += float(c)
> print total
> ----- script -----
>
> Which gave me the result I wanted.
> Since I am new to Python, I used () as a guess, and it worked.

That's fine, but its different than your original question.  In your
original question you had a string of floats separated by commas.  To
solve that problem you need to first split the string on the commas:

my_list = "1.23, 2.4, 3.123".split(",")

that will give you ['1.23', '2.4', '3.123']

>From there do what you did starting with your for loop



> --
> https://mail.python.org/mailman/listinfo/python-list



-- 
Joel Goldstick
http://joelgoldstick.com

[toc] | [prev] | [next] | [standalone]


#83568

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-01-11 23:20 +0100
Message-ID<8077448.xvuXrbCisO@PointedEars.de>
In reply to#83566
Joel Goldstick wrote:

> my_list = "1.23, 2.4, 3.123".split(",")
> 
> that will give you ['1.23', '2.4', '3.123']

No, it gives

| $ python
| Python 2.7.9 (default, Dec 11 2014, 08:58:12) 
| [GCC 4.9.2] on linux2
| Type "help", "copyright", "credits" or "license" for more information.
| >>> my_list = "1.23, 2.4, 3.123".split(",")
| >>> my_list
| ['1.23', ' 2.4', ' 3.123']
| >>>

| $ python3
| Python 3.4.2 (default, Dec 27 2014, 13:16:08) 
| [GCC 4.9.2] on linux
| Type "help", "copyright", "credits" or "license" for more information.
| >>> my_list = "1.23, 2.4, 3.123".split(",")
| >>> my_list
| ['1.23', ' 2.4', ' 3.123']
| >>> 

In order to get the result you described, one needs at least

| >>> '1.23, 2.4, 3.123'.split(', ')
| ['1.23', '2.4', '3.123']

This is safer:

| >>> from re import split
| >>> split(r'\s*,\s*', '1.23, 2.4, 3.123')
| ['1.23', '2.4', '3.123']

-- 
PointedEars

Twitter: @PointedEars2
Please do not cc me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#83572

FromJoel Goldstick <joel.goldstick@gmail.com>
Date2015-01-11 17:54 -0500
Message-ID<mailman.17599.1421016900.18130.python-list@python.org>
In reply to#83568
On Sun, Jan 11, 2015 at 5:20 PM, Thomas 'PointedEars' Lahn
<PointedEars@web.de> wrote:
> Joel Goldstick wrote:
>
>> my_list = "1.23, 2.4, 3.123".split(",")
>>
>> that will give you ['1.23', '2.4', '3.123']
>
> No, it gives
>
> | $ python
> | Python 2.7.9 (default, Dec 11 2014, 08:58:12)
> | [GCC 4.9.2] on linux2
> | Type "help", "copyright", "credits" or "license" for more information.
> | >>> my_list = "1.23, 2.4, 3.123".split(",")
> | >>> my_list
> | ['1.23', ' 2.4', ' 3.123']
> | >>>
>
> | $ python3
> | Python 3.4.2 (default, Dec 27 2014, 13:16:08)
> | [GCC 4.9.2] on linux
> | Type "help", "copyright", "credits" or "license" for more information.
> | >>> my_list = "1.23, 2.4, 3.123".split(",")
> | >>> my_list
> | ['1.23', ' 2.4', ' 3.123']
> | >>>
>
> In order to get the result you described, one needs at least
>
> | >>> '1.23, 2.4, 3.123'.split(', ')
> | ['1.23', '2.4', '3.123']
>
> This is safer:
>
> | >>> from re import split
> | >>> split(r'\s*,\s*', '1.23, 2.4, 3.123')
> | ['1.23', '2.4', '3.123']
>

I'm not sure what you are trying to point out as your examples confirm
my code.  Am I missing something.

As for feeding a beginner regex solutions, I'm on the side that this
is a terrible idea.  Regex is not something a beginner should worry
about!
> --
> PointedEars
>
> Twitter: @PointedEars2
> Please do not cc me. / Bitte keine Kopien per E-Mail.
> --
> https://mail.python.org/mailman/listinfo/python-list



-- 
Joel Goldstick
http://joelgoldstick.com

[toc] | [prev] | [next] | [standalone]


#83575

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-01-12 00:12 +0100
Message-ID<2182977.fJl0o3iPdP@PointedEars.de>
In reply to#83572
Joel Goldstick wrote:

> Thomas 'PointedEars' Lahn wrote:
>> Joel Goldstick wrote:
>>> my_list = "1.23, 2.4, 3.123".split(",")
>>>
>>> that will give you ['1.23', '2.4', '3.123']
>>
>> No, it gives
>>
>> […]
>> | >>> my_list = "1.23, 2.4, 3.123".split(",")
>> | >>> my_list
>> | ['1.23', ' 2.4', ' 3.123']
               ^       ^
>> | >>>
>>
>> In order to get the result you described, one needs at least
>>
>> | >>> '1.23, 2.4, 3.123'.split(', ')
>> | ['1.23', '2.4', '3.123']
>>
>> […]
> 
> I'm not sure what you are trying to point out as your examples confirm
> my code.

No, they don't.

> Am I missing something.
                        ^
(Is that a question.)

You are missing a leading space character because in the string the comma 
was followed by one.

> As for feeding a beginner regex solutions, I'm on the side that this
> is a terrible idea.  Regex is not something a beginner should worry
> about!

NAK.

-- 
PointedEars

Twitter: @PointedEars2
Please do not cc me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#83576

FromJoel Goldstick <joel.goldstick@gmail.com>
Date2015-01-11 18:35 -0500
Message-ID<mailman.17600.1421019325.18130.python-list@python.org>
In reply to#83575
On Sun, Jan 11, 2015 at 6:12 PM, Thomas 'PointedEars' Lahn
<PointedEars@web.de> wrote:
> Joel Goldstick wrote:
>
>> Thomas 'PointedEars' Lahn wrote:
>>> Joel Goldstick wrote:
>>>> my_list = "1.23, 2.4, 3.123".split(",")
>>>>
>>>> that will give you ['1.23', '2.4', '3.123']
>>>
>>> No, it gives
>>>
>>> […]
>>> | >>> my_list = "1.23, 2.4, 3.123".split(",")
>>> | >>> my_list
>>> | ['1.23', ' 2.4', ' 3.123']
>                ^       ^
>>> | >>>
>>>
>>> In order to get the result you described, one needs at least
>>>
>>> | >>> '1.23, 2.4, 3.123'.split(', ')
>>> | ['1.23', '2.4', '3.123']
>>>
>>> […]
>>
>> I'm not sure what you are trying to point out as your examples confirm
>> my code.
>
> No, they don't.
>
>> Am I missing something.
>                         ^
> (Is that a question.)
>
> You are missing a leading space character because in the string the comma
> was followed by one.

I see that now.  Performing float on each element of the list will
take care of that, or I guess .strip() on each first.
>
>> As for feeding a beginner regex solutions, I'm on the side that this
>> is a terrible idea.  Regex is not something a beginner should worry
>> about!
>
> NAK.
>
> --
> PointedEars
>
> Twitter: @PointedEars2
> Please do not cc me. / Bitte keine Kopien per E-Mail.
> --
> https://mail.python.org/mailman/listinfo/python-list



-- 
Joel Goldstick
http://joelgoldstick.com

[toc] | [prev] | [next] | [standalone]


#83577

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-01-12 00:46 +0100
Message-ID<1786463.stBbe1naGD@PointedEars.de>
In reply to#83576
Joel Goldstick wrote:

> On Sun, Jan 11, 2015 at 6:12 PM, Thomas 'PointedEars' Lahn
> <PointedEars@web.de> wrote:
>> Joel Goldstick wrote:
>>> Am I missing something.
>>                        ^
>> […]
>> You are missing a leading space character because in the string the comma
>> was followed by one.
> 
> I see that now.  Performing float on each element of the list will
> take care of that, or I guess .strip() on each first.

As I showed, .strip() is unnecessary.  But float() is always necessary for 
computing the sum and suffices indeed together with s.split() if s is just a 
comma-separated list of numeric strings with optional whitespace leading and 
trailing the comma:

  print(sum(map(lambda x: float(x), s.split(',')))

Please trim your quotes to the relevant minimum.

-- 
PointedEars

Twitter: @PointedEars2
Please do not cc me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#83580

FromPeter Otten <__peter__@web.de>
Date2015-01-12 01:09 +0100
Message-ID<mailman.17603.1421021375.18130.python-list@python.org>
In reply to#83577
Thomas 'PointedEars' Lahn wrote:

> Joel Goldstick wrote:
> 
>> On Sun, Jan 11, 2015 at 6:12 PM, Thomas 'PointedEars' Lahn
>> <PointedEars@web.de> wrote:
>>> Joel Goldstick wrote:
>>>> Am I missing something.
>>>                        ^
>>> […]
>>> You are missing a leading space character because in the string the
>>> comma was followed by one.
>> 
>> I see that now.  Performing float on each element of the list will
>> take care of that, or I guess .strip() on each first.
> 
> As I showed, .strip() is unnecessary.  But float() is always necessary for
> computing the sum and suffices indeed together with s.split() if s is just
> a comma-separated list of numeric strings with optional whitespace leading
> and trailing the comma:
> 
>   print(sum(map(lambda x: float(x), s.split(',')))
> 
> Please trim your quotes to the relevant minimum.

Hm, can you explain what this

lambda x: float(x)

is supposed to achieve? I mean other than to confuse a newbie...

[toc] | [prev] | [next] | [standalone]


#83583

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-01-12 01:45 +0100
Message-ID<2606109.fVWkh9SoWk@PointedEars.de>
In reply to#83580
Peter Otten wrote:

> Thomas 'PointedEars' Lahn wrote:
>> […]  But float() is always necessary for computing the sum and suffices 
>> indeed together with s.split() if s is just a comma-separated list of 
>> numeric strings with optional whitespace leading and trailing the comma:
>> 
>>   print(sum(map(lambda x: float(x), s.split(',')))
>> 
>> Please trim your quotes to the relevant minimum.
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> Hm, can you explain what this
> 
> lambda x: float(x)
> 
> is supposed to achieve? I mean other than to confuse a newbie...

  print(sum(map(float, s.split(','))))

suffices in this case, of course.

I could have done without the snide remarks.

-- 
PointedEars

Twitter: @PointedEars2
Please do not cc me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#83581

FromChris Angelico <rosuav@gmail.com>
Date2015-01-12 11:17 +1100
Message-ID<mailman.17604.1421021857.18130.python-list@python.org>
In reply to#83577
On Mon, Jan 12, 2015 at 11:09 AM, Peter Otten <__peter__@web.de> wrote:
>>
>>   print(sum(map(lambda x: float(x), s.split(',')))
>>
>> Please trim your quotes to the relevant minimum.
>
> Hm, can you explain what this
>
> lambda x: float(x)
>
> is supposed to achieve? I mean other than to confuse a newbie...

Maybe he gets paid by the character.

ChrisA

[toc] | [prev] | [next] | [standalone]


#83582

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-01-12 11:45 +1100
Message-ID<54b31929$0$13014$c3e8da3$5496439d@news.astraweb.com>
In reply to#83568
Thomas 'PointedEars' Lahn wrote:

> This is safer:
> 
> | >>> from re import split
> | >>> split(r'\s*,\s*', '1.23, 2.4, 3.123')
> | ['1.23', '2.4', '3.123']

Safer, slower, and unnecessary.

There is no need for the nuclear-powered bulldozer of regular expressions
just to crack this tiny peanut. We can split on commas, and then strip
whitespace:

py> values = "    1.234   ,    4.5678,   9.0123  ,4.321,0.9876  "
py> [s.strip() for s in values.split(',')]
['1.234', '4.5678', '9.0123', '4.321', '0.9876']


but in fact, we don't even need that, since float is perfectly happy to
accept strings with leading and trailing spaces:

py> float('            1.2345              ')
1.2345


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#83573

FromGrant Edwards <invalid@invalid.invalid>
Date2015-01-11 23:06 +0000
Message-ID<m8uvm8$omu$1@reader1.panix.com>
In reply to#83566
On 2015-01-11, Joel Goldstick <joel.goldstick@gmail.com> wrote:

> That's fine, but its different than your original question.  In your
> original question you had a string of floats separated by commas.  To
> solve that problem you need to first split the string on the commas:
>
> my_list = "1.23, 2.4, 3.123".split(",")
>
> that will give you ['1.23', '2.4', '3.123']

Well, almost:

$ python
Python 2.7.9 (default, Jan 11 2015, 15:39:24) 
[GCC 4.7.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> "1.23, 2.4, 3.123".split(",")
['1.23', ' 2.4', ' 3.123']

Note the leating whitespace in two of the elements. In this case, the
leading whitespace is ignored if you pass the values to float():

>>>map(float,"1.23, 2.4, 3.123".split(","))
[1.23, 2.4, 3.123]

Or for you young folks who prefer the more long-winded version:

>>> [float(s) for s in "1.23, 2.4, 3.123".split(",")]
[1.23, 2.4, 3.123]

In other situations, the leading whitespace might matter.

-- 
Grant


[toc] | [prev] | [next] | [standalone]


#83574

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-01-12 00:07 +0100
Message-ID<3233082.KAWmNIKqbW@PointedEars.de>
In reply to#83556
Store Makhzan wrote:

> I have this script which can calculate the total of numbers given in a
> string […]
> total = 0
> for c in '0123456789':
>    total += int(c)
> print total
> 
> […]
> How should I modify this script to find the total of if the numbers given
> in the string form have decimal places? That is, how do I need to modify
> this line: […]
> 
> for c in '1.32, 5.32, 4.4, 3.78':
> 
> […] to find the total of these given numbers.

The original script already does not do what it advertises.  Instead, it 
iterates over the characters of the string, attempts to convert each to an 
integer and then computes the sum.  That is _not_ “calculate the total of 
numbers given in a string”.

A solution has been presented, but it is not very pythonic because the 
original code was not; that should have been

### Ahh, Gauß ;-)
print(sum(map(lambda x: int(x), list('0123456789'))))
### --------------------------------------------------------------------

Also, it cannot handle non-numeric strings well.  Consider this instead:

### --------------------------------------------------------------------
from re import findall

s = '1.32, 5.32, 4.4, 3.78'
print(sum(map(lambda x: float(x), findall(r'-?\d+\.\d+', s))))
### --------------------------------------------------------------------

But if you are sure that except for the comma separator there are only 
numeric strings, it is more efficient to use re.split() instead of 
re.findall() here.


Aside:

I thought I had more than a fair grasp of regular expressions, but I am 
puzzled by

| $ python3
| Python 3.4.2 (default, Dec 27 2014, 13:16:08) 
| [GCC 4.9.2] on linux
| >>> from re import findall
| >>> s = '1.32, 5.32, 4.4, 3.78'
| >>> findall(r'-?\d+(\.\d+)?', s)
| ['.32', '.32', '.4', '.78']

Why does this more flexible pattern not work as I expected in Python 3.x, 
but virtually everywhere else?

And why this?

| >>> findall(r'-?\d+\.\d+', s)
| ['1.32', '5.32', '4.4', '3.78']
| >>> findall(r'-?\d+(\.\d+)', s)
| ['.32', '.32', '.4', '.78']

Feature?  Bug?

-- 
PointedEars

Twitter: @PointedEars2
Please do not cc me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#83579

FromMark Lawrence <breamoreboy@yahoo.co.uk>
Date2015-01-12 00:04 +0000
Message-ID<mailman.17602.1421021101.18130.python-list@python.org>
In reply to#83574
On 11/01/2015 23:07, Thomas 'PointedEars' Lahn wrote:
> Store Makhzan wrote:
>
>> I have this script which can calculate the total of numbers given in a
>> string […]
>> total = 0
>> for c in '0123456789':
>>     total += int(c)
>> print total
>>
>> […]
>> How should I modify this script to find the total of if the numbers given
>> in the string form have decimal places? That is, how do I need to modify
>> this line: […]
>>
>> for c in '1.32, 5.32, 4.4, 3.78':
>>
>> […] to find the total of these given numbers.
>
> The original script already does not do what it advertises.  Instead, it
> iterates over the characters of the string, attempts to convert each to an
> integer and then computes the sum.  That is _not_ “calculate the total of
> numbers given in a string”.
>
> A solution has been presented, but it is not very pythonic because the
> original code was not; that should have been
>
> ### Ahh, Gauß ;-)
> print(sum(map(lambda x: int(x), list('0123456789'))))
> ### --------------------------------------------------------------------
>
> Also, it cannot handle non-numeric strings well.  Consider this instead:
>
> ### --------------------------------------------------------------------
> from re import findall
>
> s = '1.32, 5.32, 4.4, 3.78'
> print(sum(map(lambda x: float(x), findall(r'-?\d+\.\d+', s))))
> ### --------------------------------------------------------------------
>
> But if you are sure that except for the comma separator there are only
> numeric strings, it is more efficient to use re.split() instead of
> re.findall() here.
>
>
> Aside:
>
> I thought I had more than a fair grasp of regular expressions, but I am
> puzzled by
>
> | $ python3
> | Python 3.4.2 (default, Dec 27 2014, 13:16:08)
> | [GCC 4.9.2] on linux
> | >>> from re import findall
> | >>> s = '1.32, 5.32, 4.4, 3.78'
> | >>> findall(r'-?\d+(\.\d+)?', s)
> | ['.32', '.32', '.4', '.78']
>
> Why does this more flexible pattern not work as I expected in Python 3.x,
> but virtually everywhere else?
>
> And why this?
>
> | >>> findall(r'-?\d+\.\d+', s)
> | ['1.32', '5.32', '4.4', '3.78']
> | >>> findall(r'-?\d+(\.\d+)', s)
> | ['.32', '.32', '.4', '.78']
>
> Feature?  Bug?
>

I can't tell you as I avoid regexes like I avoid the plague.  Having 
said that I do know that there loads of old bugs on the bug tracker, 
many of which are fixed in the "new" regex module that's available here 
https://pypi.python.org/pypi/regex/

-- 
My fellow Pythonistas, ask not what our language can do for you, ask
what you can do for our language.

Mark Lawrence

[toc] | [prev] | [next] | [standalone]


#83585

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-01-12 02:00 +0100
Message-ID<1596579.yx7AUifxch@PointedEars.de>
In reply to#83579
Mark Lawrence wrote:

> On 11/01/2015 23:07, Thomas 'PointedEars' Lahn wrote:
>> I thought I had more than a fair grasp of regular expressions, but I am
>> puzzled by
>>
>> | $ python3
>> | Python 3.4.2 (default, Dec 27 2014, 13:16:08)
>> | [GCC 4.9.2] on linux
>> | >>> from re import findall
>> | >>> s = '1.32, 5.32, 4.4, 3.78'
>> | >>> findall(r'-?\d+(\.\d+)?', s)
>> | ['.32', '.32', '.4', '.78']
>>
>> Why does this more flexible pattern not work as I expected in Python 3.x,
>> but virtually everywhere else?
>>
>> And why this?
>>
>> | >>> findall(r'-?\d+\.\d+', s)
>> | ['1.32', '5.32', '4.4', '3.78']
>> | >>> findall(r'-?\d+(\.\d+)', s)
>> | ['.32', '.32', '.4', '.78']
>>
>> Feature?  Bug?
> 
> I can't tell you

I know now why I get this result.  It is a feature, not a bug:

<https://docs.python.org/3/library/re.html?highlight=findall#re.findall>
|
| re.findall(pattern, string, flags=0)
|   Return all non-overlapping matches of pattern in string, as a list of 
|   strings. The string is scanned left-to-right, and matches are returned 
|   in the order found. If one or more groups are present in the pattern,
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|   return a list of groups; this will be a list of tuples if the pattern
    ^^^^^^^^^^^^^^^^^^^^^^^   
|   has more than one group. Empty matches are included in the result unless 
|   they touch the beginning of another match.

A solution is to use non-capturing parentheses:

| >>> findall(r'-?\d+(?:\.\d+)?', '1.32, 5.32, 4.4, 3.78')
| ['1.32', '5.32', '4.4', '3.78']

> as I avoid regexes like I avoid the plague.

You should reconsider.  Regular expressions are a powerful tool.

> Having said that I do know that there loads of old bugs on the bug 
> tracker, many of which are fixed in the "new" regex module that's 
> available here https://pypi.python.org/pypi/regex/

Interesting, thank you.

Please trim your quotes to the relevant minimum next time, though.

-- 
PointedEars

Twitter: @PointedEars2
Please do not cc me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#83584

FromMRAB <python@mrabarnett.plus.com>
Date2015-01-12 00:59 +0000
Message-ID<mailman.17605.1421024362.18130.python-list@python.org>
In reply to#83574
On 2015-01-12 00:04, Mark Lawrence wrote:
> On 11/01/2015 23:07, Thomas 'PointedEars' Lahn wrote:
>> Store Makhzan wrote:
>>
>>> I have this script which can calculate the total of numbers given in a
>>> string […]
>>> total = 0
>>> for c in '0123456789':
>>>     total += int(c)
>>> print total
>>>
>>> […]
>>> How should I modify this script to find the total of if the numbers given
>>> in the string form have decimal places? That is, how do I need to modify
>>> this line: […]
>>>
>>> for c in '1.32, 5.32, 4.4, 3.78':
>>>
>>> […] to find the total of these given numbers.
>>
>> The original script already does not do what it advertises.  Instead, it
>> iterates over the characters of the string, attempts to convert each to an
>> integer and then computes the sum.  That is _not_ “calculate the total of
>> numbers given in a string”.
>>
>> A solution has been presented, but it is not very pythonic because the
>> original code was not; that should have been
>>
>> ### Ahh, Gauß ;-)
>> print(sum(map(lambda x: int(x), list('0123456789'))))
>> ### --------------------------------------------------------------------
>>
>> Also, it cannot handle non-numeric strings well.  Consider this instead:
>>
>> ### --------------------------------------------------------------------
>> from re import findall
>>
>> s = '1.32, 5.32, 4.4, 3.78'
>> print(sum(map(lambda x: float(x), findall(r'-?\d+\.\d+', s))))
>> ### --------------------------------------------------------------------
>>
>> But if you are sure that except for the comma separator there are only
>> numeric strings, it is more efficient to use re.split() instead of
>> re.findall() here.
>>
>>
>> Aside:
>>
>> I thought I had more than a fair grasp of regular expressions, but I am
>> puzzled by
>>
>> | $ python3
>> | Python 3.4.2 (default, Dec 27 2014, 13:16:08)
>> | [GCC 4.9.2] on linux
>> | >>> from re import findall
>> | >>> s = '1.32, 5.32, 4.4, 3.78'
>> | >>> findall(r'-?\d+(\.\d+)?', s)
>> | ['.32', '.32', '.4', '.78']
>>
>> Why does this more flexible pattern not work as I expected in Python 3.x,
>> but virtually everywhere else?
>>
>> And why this?
>>
>> | >>> findall(r'-?\d+\.\d+', s)
>> | ['1.32', '5.32', '4.4', '3.78']
>> | >>> findall(r'-?\d+(\.\d+)', s)
>> | ['.32', '.32', '.4', '.78']
>>
>> Feature?  Bug?
>>
>
> I can't tell you as I avoid regexes like I avoid the plague.  Having
> said that I do know that there loads of old bugs on the bug tracker,
> many of which are fixed in the "new" regex module that's available here
> https://pypi.python.org/pypi/regex/
>
It's not a bug.

re.findall returns the capture groups, if present, or the entire match
if there are no capture groups.

In this instance, it's better to use a non-capture group:

findall(r'-?\d+(?:\.\d+)', s)

It's all in the docs! :-)

[toc] | [prev] | [next] | [standalone]


#83586

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-01-12 12:13 +1100
Message-ID<54b31fb2$0$12978$c3e8da3$5496439d@news.astraweb.com>
In reply to#83574
Thomas 'PointedEars' Lahn wrote:

> The original script already does not do what it advertises.  Instead, it
> iterates over the characters of the string, attempts to convert each to an
> integer and then computes the sum.  That is _not_ “calculate the total of
> numbers given in a string”.

Yes, and the second piece of code the Original Poster provided is even
worse:

#Check if a perfect cube
total = 0
for c in ('1.23', '2.4', '3.123'):
   print float(c)
   total += float(c)
print total


I don't see how adding up some numbers checks whether it is a perfect cube.
I guess this is a good example of this:

    At Resolver we've found it useful to short-circuit any doubt 
    and just refer to comments in code as 'lies'.

http://import-that.dreamwidth.org/956.html



> A solution has been presented, but it is not very pythonic because the
> original code was not; that should have been
> 
> ### Ahh, Gauß ;-)
> print(sum(map(lambda x: int(x), list('0123456789'))))

That can be simplified to:

sum(map(int, '0123456789'))

which can then be passed to print() if required.



> Also, it cannot handle non-numeric strings well.  Consider this instead:

The OP hasn't specified whether or not he has to deal with non-numeric
strings, or how he wants to deal with them. But my guess is that he
actually doesn't want strings at all, and needs to be taught how to work
with lists of floats and/or ints.


> ### --------------------------------------------------------------------
> from re import findall
> 
> s = '1.32, 5.32, 4.4, 3.78'
> print(sum(map(lambda x: float(x), findall(r'-?\d+\.\d+', s))))
> ### --------------------------------------------------------------------

Consider this:

py> s = '123^%#@1.2abc, %#$@2.1&*%^'
py> print(sum(map(lambda x: float(x), findall(r'-?\d+\.\d+', s))))
3.3

If your aim is just to hide the fact that you have bad data, then the regex
solution "works". Many beginners think that their job as a programmer is to
stop the program from raising an exception no matter what. But I suggest
that Postel's Law:

    Be conservative in what you emit, and liberal in what you accept.

shouldn't apply here. I don't think any reasonable person would expect that
the string "123^%#@1.2abc" should be treated as 1.2.


> Aside:
> 
> I thought I had more than a fair grasp of regular expressions, but I am
> puzzled by
> 
> | $ python3
> | Python 3.4.2 (default, Dec 27 2014, 13:16:08)
> | [GCC 4.9.2] on linux
> | >>> from re import findall
> | >>> s = '1.32, 5.32, 4.4, 3.78'
> | >>> findall(r'-?\d+(\.\d+)?', s)
> | ['.32', '.32', '.4', '.78']
> 
> Why does this more flexible pattern not work as I expected in Python 3.x,
> but virtually everywhere else?

This is documented by findall:


py> help(findall)
Help on function findall in module re:

findall(pattern, string, flags=0)
    Return a list of all non-overlapping matches in the string.

    If one or more groups are present in the pattern, return a
    list of groups; this will be a list of tuples if the pattern
    has more than one group.

    Empty matches are included in the result.



-- 
Steven

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web