在Python中深入复制列表
我有一个列表副本的问题:
所以当我从'get_edge'
得到E0
后,我通过调用'E0_copy = list(E0)'
复制E0
。 在这里,我猜E0_copy
是E0
的深层拷贝,我把E0_copy
传入'karger(E)'
。 但在主要function。
为什么for循环之前的'print E0[1:10]'
的结果与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
提前致谢!
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]]
我相信很多程序员遇到了一两个面试问题,他们被要求深度复制一个链表,但这个问题并不像听起来那么简单!
在python中,有一个叫做“copy”的模块,有两个有用的function
import copy copy.copy() copy.deepcopy()
copy()是一个浅拷贝函数,如果给定的参数是一个复合数据结构,例如一个列表 ,那么python将创build另一个相同types的对象(在本例中是一个新的列表 )只有他们的参考被复制
# think of it like newList = [elem for elem in oldlist]
直觉上,我们可以假设deepcopy()遵循相同的范例,唯一的区别是对于每个elem,我们将recursion调用deepcopy (就像mbcoder的答案一样)
但这是错误的!
deepcopy()实际上保留了原始复合数据的graphics结构:
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”,这防止不必要的重复,从而保留复制的组合数据的结构
官方文件
如果你的list elements
是immutable objects
那么你可以使用这个,否则你必须从copy
模块使用deepcopy
。
您也可以使用最短的方式来深度拷贝像这样的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]
关于列表树,python中的deep_copy可以写得最紧凑
def deep_copy(x): if not isinstance(x, list): return x else: return map(deep_copy, x)
只是一个recursion的深层复制function。
def deepcopy(A): rt = [] for elem in A: if isinstance(elem,list): rt.append(deepcopy(elem)) else: rt.append(elem) return rt
编辑:正如Cfreak提到的,这已经在copy
模块中实现。
这是比较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.
如果列表的内容是原始的,你可以使用理解
new_list = [i for i in old_list]
您可以将其嵌套为多维列表,如下所示:
new_grid = [[i for i in row] for row in grid]