在Python中,将字符串转换为数组的最快方法是什么?

6

这是我从文本文件中读取的一行:

[54, 95, 45, -97, -51, 84, 0, 32, -55, 14, 50, 54, 68, -3, 57, 88, -1]

我使用 readline() 将其读入为字符串。现在将其最快地转换回数组的方法是什么?

谢谢!


3
你有一个“列表”,而不是一个“数组”。它们之间存在一些细微的区别... - mgilson
4个回答

24

我不确定这是否是最快的方法,但肯定是最安全/最容易的方法:

import ast
lst = ast.literal_eval(s)

常规的eval也可以工作:

lst = eval(s)

我的电脑的一些基本时间:

>>> s = '[54, 95, 45, -97, -51, 84, 0, 32, -55, 14, 50, 54, 68, -3, 57, 88, -1]' 
>>> def f1():
...    eval(s)
... 
>>> def f2():
...    ast.literal_eval(s)
... 
>>> timeit.timeit('f1()', 'from __main__ import f1')
31.415852785110474
>>> timeit.timeit('f2()', 'from __main__ import f2')
46.25958704948425
所以,根据我的计算机,evalast.literal_eval 快大约50%。然而,eval 非常不安全,除非你完全信任它,否则永远不应该在任何字符串上使用。除非这是一个真正可证明的瓶颈,并且你对输入数据百分之百信任,否则我认为多花一点时间值得,换来晚上能够睡个安稳觉。

1
迄今为止最安全的是 eval(s) 可能是最快的。 - Tim Peters
1
@JonathonReinhart -- 是啊,说真的。我不确定我曾经见过它上升得那么快。 - mgilson
7
@mgilson 她说的就是这个意思。 - Jonathon Reinhart
@TimPeters -- 你说得对。在我的机器上,timeit 显示 eval 大约快50%。 - mgilson
这种使用 eval 的方式令人不安。 - Loïc Faure-Lacroix
显示剩余2条评论

18

由于我们关心速度,在这种情况下我可能会使用json.loads

>>> import ast, json
>>> s = "[54, 95, 45, -97, -51, 84, 0, 32, -55, 14, 50, 54, 68, -3, 57, 88, -1]"
>>> %timeit ast.literal_eval(s)
10000 loops, best of 3: 61.6 µs per loop
>>> %timeit eval(s)
10000 loops, best of 3: 45.7 µs per loop
>>> %timeit json.loads(s)
100000 loops, best of 3: 6.61 µs per loop
>>> json.loads(s)
[54, 95, 45, -97, -51, 84, 0, 32, -55, 14, 50, 54, 68, -3, 57, 88, -1]

请注意,这里之所以可以使用此方法是因为该行足够类似JSON格式。但它不能像ast.literal_eval那样在所有地方使用,因为并非所有Python字面量语法都是有效的JSON。


1
很酷!我想不到那个 - 令人印象深刻 :-) - Tim Peters
当然 DSM...我发了一个好答案然后你就出来超越了它。向你致敬(由于Kudos不是StackOverflow官方货币单位,加上+1作为附赠)。 - mgilson
我更喜欢使用 JSON 的解决方案,因为使用 eval 可能会出现严重的问题。 - Loïc Faure-Lacroix

3
如果这是一个字符串,可以访问这里:http://docs.python.org/2/library/functions.html#eval。该链接是关于Python中eval函数的文档。
>>> s = "[54, 95, 45, -97, -51, 84, 0, 32, -55, 14, 50, 54, 68, -3, 57, 88, -1]"
>>> eval(s)
[54, 95, 45, -97, -51, 84, 0, 32, -55, 14, 50, 54, 68, -3, 57, 88, -1]

@ᴋᴇʏsᴇʀ,我接受建议,但我不同意解释eval。它在我发布的官方Python文档中已经有了,并且在我看来,去那里阅读比在这里重复一条信息更具指导性(而且也更符合“Pythonic”)。 - Giupo
2
我并不是说这是一个坏链接:p(它绝对不是),我只是建议你至少加上一句元文本:) - keyser

0

我正在使用 Python 3.6

这是我的一个实际字符串分隔结果,使用了空格

stringValue = "123 456 789 012 345 678"

字符串转列表

intValue = list(map(int, stringValue.split(' ')))

结果

花费时间 7.586999345221557e-06

[76, 96, 127, 255, 136, 164]

尝试打印所花费的时间 6.697199933114462e-05

字符串转列表再转numpy

intValue = np.array(list(map(int, stringValue.split(' '))))

结果

花费时间 2.631999996083323e-05

[ 76 96 127 255 136 164]

尝试打印所花费的时间 0.002241893000245909

字符串转换为numpy数组

intValue = np.fromstring(stringValue,dtype=int,sep=' ')

时间花费1.3830000170855783e-05 [76 96 127 255 136 164] 尝试打印所花费的时间为0.0003395890007595881

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接