我有一个巨大的字符串元组,正在从一个程序返回。返回的示例元组可能如下所示:
('(-1,0)', '(1,0)', '(2,0)', '(3,0)', '(4,0)', '(5,0)', '(6,0)')
我可以将这些字符串转换为真正的元组(里面有整数),但我希望有人知道一个很好的技巧来加快速度。我想出的任何事情都让我觉得这样做是一种相对“缓慢”的方式。正如我所提到的,这些列表可能很大,所以快速的方式将非常受欢迎!
由于
编辑一个 好吧,所以它看起来eval是一种较慢的方法。但到目前为止,我已经测试了4种方法,感谢任何评论和提交! :)
另外,有人问我元组的大小。它的范围可以从几个,到希望不超过几百万。不是“太大”,但足够大,速度是一个重要因素。我不是在微观优化,只是学习我可能不知道的任何新的漂亮技巧。例如,eval()是我经常忘记的东西,即使在这种情况下看起来不那么好。
编辑两个 我还想注意,字符串格式不应该改变。所以不需要检查格式。此外,这是一个嵌入式Python v2.6.2,所以需要 2.6的任何东西都可以。另一方面,3.0不是那么多;)
再次感谢好人们,感谢所有的投入:)
编辑3 另一个说明。我注意到我一直在返回没有导致“元组”的代码,这没关系,如果有人认为最终结果“有”成为元组,那就很抱歉。类似格式的东西很好。
import timeit
test_tuple = ('(-1,0)', '(1,0)', '(2,0)', '(3,0)', '(4,0)', '(5,0)', '(6,0)', '(7,0)',)
def timeit_a():
''''''
def convert_tup_strings(tup_string):
first_int, last_int = tup_string[1:-1].split(',')
return (int(first_int), int(last_int))
return map(convert_tup_strings, test_tuple)
def timeit_a_1():
''''''
def convert_tup_strings(tup_string):
return map(int, tup_string[1:-1].split(','))
return map(convert_tup_strings, test_tuple)
def timeit_b():
converted = []
for tup_string in test_tuple:
first_int, last_int = tup_string[1:-1].split(',')
converted.append((int(first_int), int(last_int)))
return converted
def timeit_b_1():
converted = []
for tup_string in test_tuple:
converted.append(map(int, tup_string[1:-1].split(',')))
return converted
def timeit_c():
''''''
return [eval(t) for t in test_tuple]
def timeit_d():
''''''
return map(eval, test_tuple)
def timeit_e():
''''''
return map(lambda a: tuple(map(int, a[1:-1].split(','))), test_tuple)
print 'Timeit timeit_a: %s' % timeit.timeit(timeit_a)
print 'Timeit timeit_a_1: %s' % timeit.timeit(timeit_a_1)
print 'Timeit timeit_b: %s' % timeit.timeit(timeit_b)
print 'Timeit timeit_b_1: %s' % timeit.timeit(timeit_b_1)
print 'Timeit timeit_c: %s' % timeit.timeit(timeit_c)
print 'Timeit timeit_d: %s' % timeit.timeit(timeit_d)
print 'Timeit timeit_e: %s' % timeit.timeit(timeit_e)
结果:
Timeit timeit_a: 15.8954099772
Timeit timeit_a_1: 18.5484214589
Timeit timeit_b: 15.3137666465
Timeit timeit_b_1: 17.8405181116
Timeit timeit_c: 91.9587832802
Timeit timeit_d: 89.8858157489
Timeit timeit_e: 20.1564312947
答案 0 :(得分:10)
我建议你不要使用eval。这是缓慢而不安全的。你可以这样做:
result = map(lambda a: tuple(map(int, a[1:-1].split(','))), s)
这些数字不言自明:
timeit.Timer("map(lambda a: tuple(map(int, a[1:-1].split(','))), s)", "s = ('(-1,0)', '(1,0)', '(2,0)', '(3,0)', '(4,0)', '(5,0)', '(6,0)')").timeit(100000)
1.8787779808044434
timeit.Timer("map(eval, s)", "s = ('(-1,0)', '(1,0)', '(2,0)', '(3,0)', '(4,0)', '(5,0)', '(6,0)')").timeit(100000)
11.571426868438721
答案 1 :(得分:3)
map(eval, tuples)
这不会解释其中一个元组在语法上不正确的情况。为此,我建议像:
def do(tup):
try: return eval(tup)
except: return None
map(do, tuples)
两种方法都测试了速度:
>>> tuples = ["(1,0)"] * 1000000
>>> # map eval
>>> st = time.time(); parsed = map(eval, tuples); print "%.2f s" % (time.time() - st)
16.02 s
>>> # map do
>>> >>> st = time.time(); parsed = map(do, tuples); print "%.2f s" % (time.time() - st)
18.46 s
对于1,000,000个不是 bad 的元组(但不是伟大的)。据推测,开销是使用eval
解析Python一百万次。但是,这是做你所追求的最简单的方法。
使用列表理解而不是map
的答案与我的try / except案例一样慢(本身很有趣):
>>> st = time.time(); parsed = [eval(t) for t in tuples]; print "%.2f s" % (time.time() - st)
18.13 s
所有这一切,我要冒险过早优化在这里工作 - 解析字符串总是很慢。你期待多少元组?
答案 2 :(得分:2)
如果您知道格式,我会进行字符串解析。比eval()快。
>>> tuples = ["(1,0)"] * 1000000
>>> import time
>>> st = time.time(); parsed = map(eval, tuples); print "%.2f s" % (time.time() - st)
32.71 s
>>> def parse(s) :
... return s[1:-1].split(",")
...
>>> parse("(1,0)")
['1', '0']
>>> st = time.time(); parsed = map(parse, tuples); print "%.2f s" % (time.time() - st)
5.05 s
如果你需要整理
>>> def parse(s) :
... return map(int, s[1:-1].split(","))
...
>>> parse("(1,0)")
[1, 0]
>>> st = time.time(); parsed = map(parse, tuples); print "%.2f s" % (time.time() - st)
9.62 s
答案 3 :(得分:2)
我的电脑比Nadia慢,但运行得更快
>>> timeit.Timer(
"list((int(a),int(c)) for a,b,c in (x[1:-1].partition(',') for x in s))",
"s = ('(-1,0)', '(1,0)', '(2,0)', '(3,0)', '(4,0)', '(5,0)', '(6,0)')").timeit(100000)
3.2250211238861084
比这个
>>> timeit.Timer(
"map(lambda a: tuple(map(int, a[1:-1].split(','))), s)",
"s = ('(-1,0)', '(1,0)', '(2,0)', '(3,0)', '(4,0)', '(5,0)', '(6,0)')").timeit(100000)
3.8979239463806152
使用列表理解仍然更快
>>> timeit.Timer(
"[(int(a),int(c)) for a,b,c in (x[1:-1].partition(',') for x in s)]",
"s = ('(-1,0)', '(1,0)', '(2,0)', '(3,0)', '(4,0)', '(5,0)', '(6,0)')").timeit(100000)
2.452484130859375
答案 4 :(得分:1)
如果您确定输入结构良好:
tuples = ('(-1,0)', '(1,0)', '(2,0)', '(3,0)', '(4,0)', '(5,0)', '(6,0)')
result = [eval(t) for t in tuples]
答案 5 :(得分:1)
您可以使用YAPPS快速启动并运行解析器。
答案 6 :(得分:1)
您可以使用yaml或json将其解析为元组。
答案 7 :(得分:0)
import ast
list_of_tuples = map(ast.literal_eval, tuple_of_strings)