Google 網路論壇不再支援新的 Usenet 貼文或訂閱項目,但過往內容仍可供查看。

string to list of numbers conversion

瀏覽次數:9 次
跳到第一則未讀訊息

jm.s...@gmail.com

未讀,
2006年11月5日 清晨7:34:322006/11/5
收件者:
Hi,
I have a string '((1,2), (3,4))' and I want to convert this into a
python tuple of numbers. But I do not want to use eval() because I do
not want to execute any code in that string and limit it to list of
numbers.
Is there any alternative way?

Thanks.
Suresh

Gerard Flanagan

未讀,
2006年11月5日 上午8:00:352006/11/5
收件者:


Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit
(Intel)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>> s = '((1,2), (3,4))'
>>> s = filter(lambda char: char not in ')(', s)
>>> s
'1,2, 3,4'
>>> s = s.split(',')
>>> s
['1', '2', ' 3', '4']
>>> s = map(float, s)
>>> s
[1.0, 2.0, 3.0, 4.0]
>>> t1 = s[::2]
>>> t1
[1.0, 3.0]
>>> t2 = s[1::2]
>>> t2
[2.0, 4.0]
>>> zip(t1, t2)
[(1.0, 2.0), (3.0, 4.0)]
>>>

Gerard

Peter Otten

未讀,
2006年11月5日 上午8:00:512006/11/5
收件者:

jm.s...@gmail.com

未讀,
2006年11月5日 上午8:29:192006/11/5
收件者:
Peter, Thanks.

This recipe fails when negative numbers are used.

safe_eval('(12, -12)')
*** Unsafe_Source_Error: Line 1. Unsupported source construct:
compiler.ast.UnarySub

But, I think it could be easily fixed for somebody who understands the
script. Can somebody help.

Thanks.
Suresh

bearoph...@lycos.com

未讀,
2006年11月5日 上午9:53:212006/11/5
收件者:

This is a possibile solution, no input errors are taken into account:

>>> s = '((1,2), (3,4), (-5,9.2))'
>>> from string import maketrans
>>> tab = maketrans("(), ", " "*4)
>>> s.translate(tab)
' 1 2 3 4 -5 9.2 '
>>> l = s.translate(tab).split()
>>> l
['1', '2', '3', '4', '-5', '9.2']
>>> l2 = map(float, l)
>>> l2
[1.0, 2.0, 3.0, 4.0, -5.0, 9.1999999999999993]
>>> # This is partition(l2, 2)
>>> [l2[i:i+2] for i in xrange(0, len(l2), 2)]
[[1.0, 2.0], [3.0, 4.0], [-5.0, 9.1999999999999993]]

Bye,
bearophile

Peter Otten

未讀,
2006年11月5日 上午11:50:132006/11/5
收件者:
jm.s...@no.spam.gmail.com wrote:

> This recipe fails when negative numbers are used.
>
> safe_eval('(12, -12)')
> *** Unsafe_Source_Error: Line 1. Unsupported source construct:
> compiler.ast.UnarySub
>
> But, I think it could be easily fixed for somebody who understands the
> script.

I think that somebody could be you.

> Can somebody help.

Start with

class SafeEval(object):
# ...
def visitUnarySub(self, node, **kw):
return -node.expr.value

and then add some error handling.

Peter

Frederic Rentsch

未讀,
2006年11月6日 凌晨4:22:312006/11/6
收件者:pytho...@python.org
s = '((1,2), (3,4))'
separators = re.compile ('\(\s*\(|\)\s*,\s*\(|\)\s*\)')
tuple ([(float (n[0]), float (n[1])) for n in [pair.split (',') for pair
in separators.split (s) if pair]])
((1.0, 2.0), (3.0, 4.0))

Frederic


Paul McGuire

未讀,
2006年11月6日 清晨6:06:352006/11/6
收件者:
"jm.s...@no.spam.gmail.com" <jm.s...@gmail.com> wrote in message
news:1162730071.9...@i42g2000cwa.googlegroups.com...

Pyparsing comes with an example that parses strings representing lists.
Here's that example, converted to parsing only tuples of numbers. Note that
this does not presume that tuples are only pairs, but can be any number of
numeric values, nested to any depth, and with arbitrary whitespace, etc.
This grammar also includes converters by type, so that ints come out as
ints, and floats as floats. (This grammar doesn't handle empty tuples, but
it does handle tuples that include an extra ',' after the last tuple
element.)

-- Paul
Download pyparsing at http://sourceforge.net/projects/pyparsing/ .


from pyparsing import *

integer = (Word(nums)|Word('-+',nums)).setName("integer")
real = Combine(integer + "." + Optional(Word(nums))).setName("real")
tupleStr = Forward().setName("tuple")
tupleItem = real | integer | tupleStr
tupleStr << ( Suppress("(") + delimitedList(tupleItem) +
Optional(Suppress(",")) + Suppress(")") )

# add parse actions to do conversion during parsing
integer.setParseAction( lambda toks: int(toks[0]) )
real.setParseAction( lambda toks: float(toks[0]) )
tupleStr.setParseAction( lambda toks: tuple(toks) )

s = '((1,2), (3,4), (-5,9.2),)'
print tupleStr.parseString(s)[0]

Gives:
((1, 2), (3, 4), (-5, 9.1999999999999993))


Fredrik Lundh

未讀,
2006年11月6日 上午10:51:222006/11/6
收件者:pytho...@python.org
jm.s...@no.spam.gmail.com wrote:

> I have a string '((1,2), (3,4))' and I want to convert this into a
> python tuple of numbers. But I do not want to use eval() because I do
> not want to execute any code in that string and limit it to list of
> numbers.

here's yet another approach:

http://online.effbot.org/2005_11_01_archive.htm#simple-parser-1

also see:

http://online.effbot.org/2005_11_01_archive.htm#simple-parser-3

</F>

henning

未讀,
2006年11月8日 晚上11:10:132006/11/8
收件者:
jm.s...@no.spam.gmail.com skrev:

> Hi,
> I have a string '((1,2), (3,4))' and I want to convert this into a
> python tuple of numbers.

I think your question is deeper and more natural than is clear from the
many recepies given so far in this thread, so I'll take on another
point of view,

>From a language design perspective, there is no reason why not the
parsing capacity of the Python interpreter would be accessible in a
modular fashion to the user/programmer. E.g used like this:

I an imaginable Python, define you expect for an answer. In this case:
(1)
# import junctions, types from maybefuture:-)
string = ((1,2), (3,4))
type a = tuple a | int
myTuple = eval(string, goal=a)


Obviously, if you expect _only_ the given form, then this might be
better:

(2)
# import types from maybefuture:-)
type a = ((int,int),(int,int))
myTuple = eval(string, goal=a)

Note the use of a "a|b" in line 2 (I think Perl 6 is among the few
programming languages giving a reasonable semantics to junctions so
far).

Version 2 above sholud not be a big addition to Python conceptually.
Motivation:
It is easy to think clearly about.
It makes it easier to use eval safely and makes code more readable.

This is a topic of interest to me, so feel free to post either on list
or directly to me.

Thanks/Henning

0 則新訊息