在Python中创建"反向"列表的最佳方法是什么?
在Python中,如何创建一个新列表,这个新列表的内容和另一个列表的内容一样,但顺序是反过来的?(我不想直接改动原来的列表。)
这里有一个我想到的解决办法:
new_list = list(reversed(old_list))
还可以先复制一份old_list
,然后把复制的列表反转:
new_list = list(old_list) # or `new_list = old_list[:]`
new_list.reverse()
有没有更好的方法我没想到?如果没有的话,以上这些方法中,有没有哪个在效率上更好一些?
3 个回答
11
调整
这里值得提一下,sdolan 提供的 timeit 计算结果中,给出了一个基准参考,展示了 'reversed' 的性能,而没有使用通常不必要的 list()
转换。这个 list()
操作会额外增加 26 微秒的运行时间,只有在迭代器不合适的情况下才需要使用。
结果:
reversed(lst) -- 11.2 usecs
list(reversed(lst)) -- 37.1 usecs
lst[::-1] -- 23.6 usecs
计算:
# I ran this set of 100000 and came up with 11.2, twice:
python -m timeit "ol = [1, 2, 3]*1000; nl = reversed(ol)"
100000 loops, best of 3: 11.2 usec per loop
# This shows the overhead of list()
python -m timeit "ol = [1, 2, 3]*1000; nl = list(reversed(ol))"
10000 loops, best of 3: 37.1 usec per loop
# This is the result for reverse via -1 step slices
python -m timeit "ol = [1, 2, 3]*1000;nl = ol[::-1]"
10000 loops, best of 3: 23.6 usec per loop
结论:
这些测试的结论是,reversed()
比切片 [::-1]
快 12.4 微秒。
65
现在我们来看看timeit
这个工具。提示:Alex 提到的 [::-1]
是最快的哦 :)
$ p -m timeit "ol = [1, 2, 3]; nl = list(reversed(ol))"
100000 loops, best of 3: 2.34 usec per loop
$ p -m timeit "ol = [1, 2, 3]; nl = list(ol); nl.reverse();"
1000000 loops, best of 3: 0.686 usec per loop
$ p -m timeit "ol = [1, 2, 3]; nl = ol[::-1];"
1000000 loops, best of 3: 0.569 usec per loop
$ p -m timeit "ol = [1, 2, 3]; nl = [i for i in reversed(ol)];"
1000000 loops, best of 3: 1.48 usec per loop
$ p -m timeit "ol = [1, 2, 3]*1000; nl = list(reversed(ol))"
10000 loops, best of 3: 44.7 usec per loop
$ p -m timeit "ol = [1, 2, 3]*1000; nl = list(ol); nl.reverse();"
10000 loops, best of 3: 27.2 usec per loop
$ p -m timeit "ol = [1, 2, 3]*1000; nl = ol[::-1];"
10000 loops, best of 3: 24.3 usec per loop
$ p -m timeit "ol = [1, 2, 3]*1000; nl = [i for i in reversed(ol)];"
10000 loops, best of 3: 155 usec per loop
更新:添加了 inspectorG4dget 提出的列表推导方法。我会让结果自己说话。
232
newlist = oldlist[::-1]
这个 [::-1]
切片(我妻子安娜喜欢叫它“火星人微笑”;-))的意思是:把整个序列反向切片,也就是从后往前切。这个方法适用于所有类型的序列。
需要注意的是,这个方法(以及你提到的其他方法)是等同于“浅拷贝”的,也就是说:如果里面的元素是可变的(可以改变的),当你对它们进行修改时,原始列表中的元素和反转后的列表中的元素会同时发生变化,反之亦然。如果你想避免这种情况,使用 copy.deepcopy
(虽然这个操作可能会比较耗费资源),然后再用 .reverse
,这是唯一好的选择。