python - 连接字符串比附加到列表更快

标签 python string performance list python-3.x

我正在尝试隔离列表中的特定项目(例如 [0, 1, 1] 将返回 [0, 1])。我设法解决了这个问题,但我注意到了一些奇怪的事情。

当我尝试追加到列表时,它的运行速度比我连接字符串然后拆分它时慢了大约 7 倍。

这是我的代码:

import time
start = time.time()

first = [x for x in range(99999) if x % 2 == 0]
second = [x for x in range(99999) if x % 4 == 0]

values = first + second

distinct_string = ""

for i in values:
    if not str(i) in distinct_string:
        distinct_string += str(i) + " "

print(distinct_string.split())

print(" --- %s sec --- " % (start - time.time()))

此结果将在大约 5 秒后结束... 现在是列表:

import time
start = time.time()

first = [x for x in range(99999) if x % 2 == 0]
second = [x for x in range(99999) if x % 4 == 0]

values = first + second

distinct_list = []

for i in values:
    if not i in distinct_list:
        distinct_list.append(i)

print(distinct_list)

print(" --- %s sec --- " % (start - time.time()))

大约运行 40 秒。

即使我将大量值转换为字符串,是什么让字符串更快?

最佳答案

请注意,通常最好使用 timeit 来比较函数,它会多次运行同一事物以获得平均性能,并分解出重复的代码以专注于重要的性能。这是我的测试脚本:

first = [x for x in range(999) if x % 2 == 0]
second = [x for x in range(999) if x % 4 == 0]

values = first + second

def str_method(values):
    distinct_string = ""
    for i in values:
        if not str(i) in distinct_string:
            distinct_string += str(i) + " "
    return [int(s) for s in distinct_string.split()]

def list_method(values):
    distinct_list = []
    for i in values:
        if not i in distinct_list:
            distinct_list.append(i)
    return distinct_list

def set_method(values):
    seen = set()
    return [val for val in values if val not in seen and seen.add(val) is None]

if __name__ == '__main__':
    assert str_method(values) == list_method(values) == set_method(values)
    import timeit
    funcs = [func.__name__ for func in (str_method, list_method, set_method)]
    setup = 'from __main__ import {}, values'.format(', '.join(funcs))
    for func in funcs:
        print(func)
        print(timeit.timeit(
            '{}(values)'.format(func),
            setup=setup,
            number=1000
        ))

我添加了 int 转换以确保函数返回相同的东西,并得到以下结果:

str_method
1.1685157899992191
list_method
2.6124089090008056
set_method
0.09523714500392089

请注意,如果必须转换输入,则在列表中搜索比在字符串中搜索更快是不正确的:

>>> timeit.timeit('1 in l', setup='l = [9, 8, 7, 6, 5, 4, 3, 2, 1]')
0.15300405000016326
>>> timeit.timeit('str(1) in s', setup='s = "9 8 7 6 5 4 3 2 1"')
0.23205067300295923

重复 append 到列表不是很有效,因为这意味着要频繁调整底层对象的大小 - 列表理解,如 set 版本所示,是效率更高。

关于python - 连接字符串比附加到列表更快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32920991/

相关文章:

python - 具有分水岭的连通对象的图像分割

python - 如何检查变量的类型是否为字符串?

c - 带有注释(编译指示)的仪器 C 代码用于性能跟踪

javascript - onkeyup 事件触发延迟

python - 在 Django 中通过外键选择相关字段

python - 当您打开文件夹时,VS Code 如何处理文件位置?

python - Django 应用找不到环境变量

java - 清理包含二进制垃圾的输入字符串以生成 ASCII 可打印字符串

html - 带有 HTML 实体的 XSLT 字符串 - 如何让它呈现为 HTML?

javascript - 阻塞函数的更好、更有效的方法是什么?