繁体   English   中英

将'(-1,0)'转换为元组(-1,0)的最快方法?

[英]Fastest way to convert '(-1,0)' into tuple(-1, 0)?

我有一个很大的字符串元组,这些字符串是从程序中返回的。 返回的示例元组可能如下所示:

('(-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

我不建议您完全使用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
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个元组来说,这还不错 (但也不是很好 )。 据推测,开销是使用eval解析Python一百万次。 但是,这是您要做的最简单的方法。

使用列表推导而不是map的答案大约和我的try / except情况一样慢(本身很有趣):

>>> st = time.time(); parsed = [eval(t) for t in tuples]; print "%.2f s" % (time.time() - st)
18.13 s

话虽如此,我要冒险过早优化在这里起作用-解析字符串总是很慢。 您期望多少个元组?

如果您知道格式,我会进行字符串解析。 比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

我的计算机比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

如果您确定输入格式正确:

tuples = ('(-1,0)', '(1,0)', '(2,0)', '(3,0)', '(4,0)', '(5,0)', '(6,0)')
result = [eval(t) for t in tuples]

您可以使用YAPPS启动解析器并使其快速运行。

您可以只使用yaml或json将其解析为元组。

import ast

list_of_tuples = map(ast.literal_eval, tuple_of_strings)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM