列表中所有字符串的长度:最快的方式

 手机用户2702933567 发布于 2023-01-29 20:56

我尝试着:

python3 -m timeit -c 'len("".join([str(x) for x in range(0, 999999)]))'
10 loops, best of 3: 330 msec per loop

python3 -m timeit -c 'sum((len(y) for y in [str(x) for x in range(0, 999999)]))
10 loops, best of 3: 439 msec per loop

为什么会这样?有更快的方法吗?

PS假设字符串列表将提前.

1 个回答
  • 暂时忽略那个相当小的时差,你的两种记忆方式实际上存在巨大差异.

    sum((len(y) for y in [str(x) for x in range(0, 999999)]))
    

    这将为每个数字创建一个字符串并将其存储在列表中.然后使用生成器表达式循环遍历该列表并将长度相加.所以你基本上每个数字都有一个字符串,一个存储所有字符串的列表,以及一个为长度添加的数字.

    len(''.join([str(x) for x in range(0, 999999)]))
    

    这将再次为每个数字创建一个字符串并将其存储在列表中.然后你创建一个包含所有数字的巨大字符串.然后你调用长度(然后是O(1)调用).所以你没有你添加的数字(总结长度),但你有另一个长字符串再次组合所有其他字符串.

    因此,即使速度更快,您也会丢弃大量内存,这可能会对以后的性能产生影响.

    为了改善这一切,您应该考虑尽可能永久地创建小东西.不要使用列表推导,因为它实际上会创建列表; 不要使用,str.join因为它需要一个列表并迭代它两次.

    sum(len(str(x)) for x in range(0, 999999)))
    

    现在,这仍然比len(''.join(…))方法慢,但不会有那么多的内存开销.实际上,它一次只创建一个字符串对象,获取其长度并将其添加到总和中.然后可以立即收集字符串.

    这仍然将是缓慢的,虽然原因是,它都lenstr必须抬起头来,发电机内的每个迭代.为了提高速度,请使用map仅查找两次.wim在评论中提出了一个非常好的建议:

    sum(map(len, map(str, range(999999))))
    

    这实际上比len(''.join(…))我的方式更快.我的时间顺序在我的回答中提到:

    62.36836282166257
    50.54277449168785
    58.24419845897603
    40.3403849521618
    

    2023-01-29 20:59 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有