【问题标题】:Python String-Iteration/Manipulation Speed-StrategyPython 字符串迭代/操作速度策略
【发布时间】:2018-04-24 17:05:30
【问题描述】:

假设您想通过使用算法将字符串“abcdefgh”更改为“fbcheagd”来操作字符串。下面哪种策略可以让程序更快地完成,或者它们都以平局结束?

方案一:

msg,out,key = 'abcdefgh',str(),[5,1,2,7,4,0,6,3]
for i in key:
     out += msg[i]
msg = out
print(msg)

方案二:

msg,out = 'abcdefgh',str()
key = {'a':'f','b':'b','c':'c','d':'h','e':'e','f':'a','g':'g','h':'d'}
for i in msg:
     out += key[i]
msg = out
print(msg)

【问题讨论】:

  • 两者都不是。两者都会很慢,因为字符串连接是 O(n) 并且很浪费。追加到一个列表,最后调用''.join
  • 更好 - 如果你有一个字典,就像在第二种情况下一样,使用str.translate
  • @cᴏʟᴅsᴘᴇᴇᴅ:作为 CPython 实现细节,它对字符串进行就地突变;它每次都必须reallocstr 不会保持与长度分开的容量),但实际上许多reallocs 不必移动内存(它们只是占用了更多的空间空间),所以它接近于摊销的O(n)。并不是说您应该依赖它;它仅适用于 CPython,并且仅适用于 str 类型(不适用于 Py2 上的 unicode 或 Py3 上的 bytes)。 ''.join 是可移植的,并且渐进地更快。
  • 至于实际问题,我有点不清楚比较的意义是什么。其中一个是进行索引洗牌,另一个是执行字符翻译。虽然在这种情况下两者都得到相同的效果,但它不会转化为不同的输入;例如,如果输入具有重复字符,则字符转换无法复制任意 shuffle,但转换表不一定会随着输入大小而增长,而 shuffle 必须随着输入大小增加索引 list 大小。这归结为问“哪个更快,橙色还是猫?”
  • 毕竟,如果我们忽略每个算法适用的完全不同的领域,我们可以说out = "fbcheagd" 获胜并完全跳过循环(甚至查看输入字符串)。

标签: python string algorithm performance sorting


【解决方案1】:

也许我们可以尝试使用 python 内置函数和一个单行。

In [1]: msg='abcdefgh'

In [2]: key=[5,1,2,7,4,0,6,3]

In [3]: ''.join(zip(*sorted(zip(list(msg), key), key=lambda item:item[1]))[0])
Out[3]: 'fbcheagd'

不是一个大粉丝,因为 oneliner 在这样组合时会影响可读性,但它确实有效。

【讨论】:

  • 虽然很有趣也很棘手,但这实际上比等效的方法 1 慢(理论上和实践上)。大 O 是 O(n log n)(感谢通用排序)而不是 O(n),在本地测试中,运行时间要长 3-4 倍(即使在删除了像 msg 包装在 list() 中这样的浪费的东西之后,这会无缘无故地浪费时间),即使输入很小。它也是不可移植的(需要调整才能在 Py3 上工作,其中 zip 返回一个迭代器,而不是 list)。 ''.join([msg[i] for i in key]) 更快更简洁。
  • 我 100% 同意你的观点。只是想到了一个让我印象深刻的不同算法。
猜你喜欢
  • 2013-08-09
  • 1970-01-01
  • 1970-01-01
  • 2019-07-15
  • 2011-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多