在不需要额外内存的情况下将python列表一分为二
我想将在不需要额外内存的情况下将python列表一分为二,python,list,Python,List,我想将int列表l拆分为两个小列表l1,l2(我知道拆分点n) 我已经能够通过复制另一个列表中的l2元素,然后将它们从l中删除来执行拆分,但这需要内存中至少有n+n/2元素的空间,这是不可承受的,因为l很大 有人有解决办法吗?试试这个怎么样 class mylist(list): def split_by_position_n(self, n): return self[:int(n)], self[int(n):] 然后,l=mylist(范围(1,10)) 您可以使
int
列表l
拆分为两个小列表l1
,l2
(我知道拆分点n
)
我已经能够通过复制另一个列表中的l2
元素,然后将它们从l
中删除来执行拆分,但这需要内存中至少有n+n/2
元素的空间,这是不可承受的,因为l
很大
有人有解决办法吗?试试这个怎么样
class mylist(list):
def split_by_position_n(self, n):
return self[:int(n)], self[int(n):]
然后,l=mylist(范围(1,10))
您可以使用at
n
对列表进行切片。切片对象是惰性的,只有在迭代时才会加载到内存中:
from itertools import islice
def split_list(lst, n):
return islice(lst, n), islice(lst, n, None)
A, B = split_list(range(10), 5)
print(list(A))
# [0, 1, 2, 3, 4]
print(list(B))
# [5, 6, 7, 8, 9]
海洛阿雷托
这是我的解决方案:
list = [1,2,3,4,5,6,7,8,9]
l1 = list[0:n]
l2 = list[n:]
- 列表是元素的列表
- n是第一个列表(拆分点索引)中所需的元素数
编辑:如果您担心内存问题,可以在拆分列表后将其删除。。即使您可以在代码中使用list[0:n]/list[n:],也不会占用更多内存 如果您不想在较小的列表上花费额外的内存,有两种可能:
>>> from collections import deque
>>> deq = deque(range(20))
>>> front = deque(deq.popleft() for _ in range(10))
>>> front
deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> deq # original list reduced, can be used as 2nd list
deque([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
numpy.array
,并在该数组上创建切片(即视图):
>>> import numpy as np
>>> arr = np.array(range(20))
>>> front = arr[:10]
>>> back = arr[10:]
>>> front[3] = 100
>>> arr # original list modified
array([ 0, 1, 2, 100, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19])
list
,也可以使用list.pop
。但是,如中所述,您不应使用pop(0)
,因为每次弹出元素时,都必须重新组织整个列表,从而为您提供O(n²)来提取列表的一半。相反,使用pop()
从列表末尾弹出。要恢复原始顺序,可以先弹出到临时列表中,然后从该列表中弹出,将其反转两次
>>> lst = list(range(10))
>>> tmp = [lst.pop() for _ in range(5)]
>>> front, back = lst, [tmp.pop() for _ in range(len(tmp))]
>>> front, back
([0, 1, 2, 3, 4], [5, 6, 7, 8, 9])
我提出了一个简单的解决方案。那怎么办
l1 = [l.pop(0) for i in range(n)]
它似乎可以工作,不需要额外的内存。可能会重复为什么要拆分?您可以构造某种类型的“视图”,将列表的一部分视为完整列表issue@asongtoruin:此问题更具体地说明了如何在不造成巨大内存负担的情况下执行此操作。@WillemVanonSeuming for a view似乎是一个不错的选择这与我的第一个解决方案类似,但请注意,在常规列表中,
pop(0)
非常浪费。您不需要额外的内存,但对于每个pop
,所有元素都必须重新定位。最好使用deque
。事实上,甚至在列表中提到了pop(0)
的O(n)内存开销,这正是您试图避免的。(误读文档,这是移动内存的O(n)开销,不是O(n)内存开销,但仍然是弹出一半列表的二次复杂度,如果列表很长,这是非常糟糕的。)@tobias_kpop()
仅限?移动元件是否需要O(n)成本?我真的不需要让元素保持有序。pop()
不应该那么糟糕;随着列表的缩小,它可能仍会不时地进行一些秘密的数据重组,li
中的元素将被反转,但除此之外。。。为了确保你只需要尝试一下你的大名单。尽管如此,使用deque
有什么错?好吧deque
不是list
或list
的子类,我一定要使用deque
类,而不使用list
类的所有特性,或者做一些类似deq=deque(l)
然后l=list(deq)
。在你的回答中把我的选择作为第三个选择,连同这些考虑因素,会有帮助吗?
l1 = [l.pop(0) for i in range(n)]