问题:如何深层复制列表?
我对列表副本有一些问题:
所以之后我得到了E0
来自'get_edge'
,我做的副本E0
通过调用'E0_copy = list(E0)'
。我想E0_copy
是这里的深复制E0
,我E0_copy
走进了'karger(E)'
。但是在主要功能上。
为什么'print E0[1:10]'
for循环之前的结果与for循环之后的结果不同?
下面是我的代码:
def get_graph():
f=open('kargerMinCut.txt')
G={}
for line in f:
ints = [int(x) for x in line.split()]
G[ints[0]]=ints[1:len(ints)]
return G
def get_edge(G):
E=[]
for i in range(1,201):
for v in G[i]:
if v>i:
E.append([i,v])
print id(E)
return E
def karger(E):
import random
count=200
while 1:
if count == 2:
break
edge = random.randint(0,len(E)-1)
v0=E[edge][0]
v1=E[edge][1]
E.pop(edge)
if v0 != v1:
count -= 1
i=0
while 1:
if i == len(E):
break
if E[i][0] == v1:
E[i][0] = v0
if E[i][1] == v1:
E[i][1] = v0
if E[i][0] == E[i][1]:
E.pop(i)
i-=1
i+=1
mincut=len(E)
return mincut
if __name__=="__main__":
import copy
G = get_graph()
results=[]
E0 = get_edge(G)
print E0[1:10] ## this result is not equal to print2
for k in range(1,5):
E0_copy=list(E0) ## I guess here E0_coypy is a deep copy of E0
results.append(karger(E0_copy))
#print "the result is %d" %min(results)
print E0[1:10] ## this is print2
回答 0
E0_copy
不是深层副本。你不使用做出深层副本list()
(两者list(...)
并testList[:]
很浅拷贝)。
您copy.deepcopy(...)
用于深度复制列表。
deepcopy(x, memo=None, _nil=[])
Deep copy operation on arbitrary Python objects.
请参阅以下代码段-
>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = list(a)
>>> a
[[1, 2, 3], [4, 5, 6]]
>>> b
[[1, 2, 3], [4, 5, 6]]
>>> a[0][1] = 10
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b # b changes too -> Not a deepcopy.
[[1, 10, 3], [4, 5, 6]]
现在看deepcopy
操作
>>> import copy
>>> b = copy.deepcopy(a)
>>> a
[[1, 10, 3], [4, 5, 6]]
>>> b
[[1, 10, 3], [4, 5, 6]]
>>> a[0][1] = 9
>>> a
[[1, 9, 3], [4, 5, 6]]
>>> b # b doesn't change -> Deep Copy
[[1, 10, 3], [4, 5, 6]]
回答 1
我相信很多程序员遇到一个或两个面试问题,他们被要求深度复制链表,但是这个问题比听起来要难!
在python中,有一个名为“ copy”的模块,具有两个有用的功能
import copy
copy.copy()
copy.deepcopy()
如果给定参数是复合数据结构,例如,则copy()是浅表复制函数。 list,则python将创建另一个相同类型的对象(在这种情况下为new list),但对于旧列表中的所有对象,仅复制他们的参考
# think of it like
newList = [elem for elem in oldlist]
直观地,我们可以假定deepcopy()遵循相同的范例,唯一的区别是对于每个元素,我们将递归调用deepcopy,(就像mbcoder的答案一样)
但这是错误的!
deepcopy()实际上保留了原始化合物数据的图形结构:
a = [1,2]
b = [a,a] # there's only 1 object a
c = deepcopy(b)
# check the result
c[0] is a # return False, a new object a' is created
c[0] is c[1] # return True, c is [a',a'] not [a',a'']
这是棘手的部分,在deepcopy()过程中,哈希表(python中的字典)用于映射:“ old_object ref到new_object ref”,这可以防止不必要的重复,从而保留复制的复合数据的结构
回答 2
如果列表的内容是原始数据类型,则可以使用理解
new_list = [i for i in old_list]
您可以将其嵌套为多维列表,例如:
new_grid = [[i for i in row] for row in grid]
回答 3
如果list elements
是,immutable objects
则可以使用它,否则必须使用deepcopy
from copy
模块。
您也可以使用最短的方式进行list
类似的深层复制。
a = [0,1,2,3,4,5,6,7,8,9,10]
b = a[:] #deep copying the list a and assigning it to b
print id(a)
20983280
print id(b)
12967208
a[2] = 20
print a
[0, 1, 20, 3, 4, 5, 6, 7, 8, 9,10]
print b
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10]
回答 4
只是递归的深层复制功能。
def deepcopy(A):
rt = []
for elem in A:
if isinstance(elem,list):
rt.append(deepcopy(elem))
else:
rt.append(elem)
return rt
编辑:正如Cfreak所述,这已经在copy
模块中实现。
回答 5
关于列表作为树,Python中的deep_copy可以写成最紧凑的形式:
def deep_copy(x):
if not isinstance(x, list): return x
else: return map(deep_copy, x)
回答 6
这是如何深度复制列表的示例:
b = [x[:] for x in a]
回答 7
这更pythonic
my_list = [0, 1, 2, 3, 4, 5] # some list
my_list_copy = list(my_list) # my_list_copy and my_list does not share reference now.
注意:这是不安全的引用对象的列表