有没有办法从一长串数字的开头删除元素?现在我正在做del arr [i:i + x],但它很慢,因为它必须将所有内容移动到该点左侧,这对于大型列表来说非常耗时。
我调查了deques但不确定这些是否适用于此。可以用一些方向!
答案 0 :(得分:3)
是deque
在这里适用,你应该使用它们,如果它们非常靠近前面它会非常快,但如果起始索引位于中间位置则会慢一些。
索引访问在两端都是O(1),但在中间减慢到O(n)。
>>> from collections import deque
>>> def delete_slice(d, start, stop):
d.rotate(-start)
for i in range(stop-start): # use xrange on Python 2
d.popleft()
d.rotate(start)
>>> d = deque(range(15))
>>> delete_slice(d, 5, 10)
>>> d
deque([0, 1, 2, 3, 4, 10, 11, 12, 13, 14])
注意:如前所述,旋转过中间位置会很慢,如果你想从右侧支持快速删除,你可以像这样扩展代码:
def delete_slice(d, start, stop):
stop = min(stop, len(d)) # don't go past the end
start = min(start, stop) # don't go past stop
if start < len(d) // 2:
d.rotate(-start)
for i in range(stop-start): # use xrange on Python 2
d.popleft()
d.rotate(start)
else:
n = len(d) - stop
d.rotate(n)
for i in range(stop - start):
d.pop()
d.rotate(-n)
当然还有一些其他的错误检查,你需要做,但为了简单起见,我会把它留在这里。遗憾的是,deque
本身尚未提供这些方法,因此您必须像这样实现它们。
要实现双端切片,请使用类似的方法应用
rotate()
将目标元素置于deque
的左侧。使用popleft()
删除旧条目,使用extend()
添加新条目,然后反转轮播。通过该方法的微小变化,可以轻松实现Forth样式堆栈操作,例如dup,drop,swap,over,pick,rot和roll。
答案 1 :(得分:1)
是的,deque
适用于此处。准备了一个展示如何使用它的例子:
import collections
"create deque from list"
d=collections.deque([1,2,3,4,5,6])
"remove first element"
d.popleft()
print d
输出:
deque([2,3,4,5,6])
答案 2 :(得分:0)
如果您连续进行多次删除,使用带过滤器的生成器创建新列表可能更有效:
arr = [e for e in arr if not rejected(e)]
如果需要使用索引,可以使用enumerate:
arr = [e for i, e in enumerate(arr) if not rejected(i)]
两个操作都是O(n)(空间中的O(2 * n)),而连续执行多个删除是O(n * m)(但空间中的O(n))。
deque
有这个特征,可能不是你想要的:
索引访问在两端都是O(1),但在中间减慢到O(n)。
答案 3 :(得分:0)
我想你可能想要一棵树或跳过清单。
我前段时间研究过Python树的实现: http://stromberg.dnsalias.org/~strombrg/python-tree-and-heap-comparison/
您可能最好在网站的算法部分询问此事。
答案 4 :(得分:0)
列表未针对在前面追加或弹出进行优化。不过,双端队列是。
还要注意 the CPython implementation 中的 deque.remove(item)
将从前面搜索。如果您需要频繁移动/删除队列项目,您可能会受益于考虑大多数要删除的项目是否将接近尾声,如果是这种情况,则使用翻转的队列,即 appendleft
和 pop
而不是 append
和 popleft
。