lista - python copy variable
Copia profunda de una lista en Python (7)
Tengo algún problema con una copia de la lista:
Entonces, después de obtener E0
de ''get_edge''
, hago una copia de E0
llamando ''E0_copy = list(E0)''
. Aquí supongo que E0_copy
es una copia profunda de E0
, y paso E0_copy
a ''karger(E)''
. Pero en la función principal.
¿Por qué el resultado de ''print E0[1:10]''
antes del bucle for no es el mismo que después del bucle for?
A continuación está mi código:
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
¡Gracias por adelantado!
Creo que muchos programadores se han encontrado con uno o dos problemas de entrevista en los que se les pide que copien en profundidad una lista vinculada, ¡pero este problema no es tan fácil como parece!
en python, hay un módulo llamado "copiar" con dos funciones útiles
import copy
copy.copy()
copy.deepcopy()
copy () es una función de copia superficial, si el argumento dado es una estructura de datos compuesta, por ejemplo una lista , entonces python creará otro objeto del mismo tipo (en este caso, una nueva lista ) pero para todo dentro de la lista anterior, solo se copia su referencia
# think of it like
newList = [elem for elem in oldlist]
Intuitivamente, podríamos suponer que deepcopy () seguiría el mismo paradigma, y la única diferencia es que por cada elemento llamaremos recursivamente a deepcopy , (al igual que la respuesta de mbcoder)
pero esto está mal!
deepcopy () en realidad conserva la estructura gráfica de los datos compuestos originales:
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'''']
esta es la parte difícil, durante el proceso de deepcopy () se usa una tabla hash (diccionario en python) para mapear: "ref old_object en ref new_object", esto evita duplicados innecesarios y así preserva la estructura de los datos compuestos copiados
En cuanto a la lista como árbol, deep_copy en python se puede escribir de forma más compacta
def deep_copy(x):
if not isinstance(x, list): return x
else: return map(deep_copy, x)
Esto es más pitónico
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.
NOTA: Esto no es seguro con una lista de tipos mutables
Si los list elements
su list elements
son immutable objects
, puede usar esto; de lo contrario, debe utilizar deepcopy
desde el módulo de copy
.
también puede usar la forma más corta para copiar en profundidad una list
como esta.
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]
Si los contenidos de la lista son tipos de datos primitivos, puede usar una comprensión
new_list = [i for i in old_list]
Puede anidarlo para listas multidimensionales como:
new_grid = [[i for i in row] for row in grid]
solo una función de copia profunda recursiva.
def deepcopy(A):
rt = []
for elem in A:
if isinstance(elem,list):
rt.append(deepcopy(elem))
else:
rt.append(elem)
return rt
Editar: Como mencionó Cfreak, esto ya está implementado en el módulo de copy
.
E0_copy
no es una copia profunda. No hace una copia profunda usando list()
(Both list(...)
y testList[:]
son copias superficiales).
Utiliza copy.deepcopy(...)
para copiar profundamente una lista.
deepcopy(x, memo=None, _nil=[])
Deep copy operation on arbitrary Python objects.
Vea el siguiente fragmento:
>>> 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]]
Ahora vea la operación de 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]]