Как глубоко скопировать список?
у меня есть некоторые проблемы с копией списка:
так что после того, как я получил 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
7 ответов:
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 есть модуль под названием "копировать" с двумя полезными функциями
import copy copy.copy() copy.deepcopy()copy () является мелкой функцией копирования, если данный аргумент является составной структурой данных, например a список, затем python создаст другой объект того же типа (в этом случае a новый список) но для всего внутри старого списка копируется только их ссылка
# think of it like newList = [elem for elem in oldlist]интуитивно мы могли бы предположить, что deepcopy () будет следовать той же парадигме, и единственное различие заключается в том, что для каждого elem мы будем рекурсивно называть 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", это предотвращает ненужные дубликаты и таким образом сохраняет структуру скопированных составных данных
если содержимое списка являются примитивными типами данных, вы можете использовать понимание
new_list = [i for i in old_list]вы можете вложить его для многомерных списков, таких как:
new_grid = [[i for i in row] for row in grid]
если
list elementsareimmutable objectsтогда вы можете использовать это, в противном случае вы должны использоватьdeepcopyС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]
просто рекурсивная функция глубокого копирования.
def deepcopy(A): rt = [] for elem in A: if isinstance(elem,list): rt.append(deepcopy(elem)) else: rt.append(elem) return rtEdit: Как упоминалось в Cfreak, это уже реализовано в
copyмодуль.
Что касается списка как дерева, то deep_copy в python можно наиболее компактно записать как
def deep_copy(x): if not isinstance(x, list): return x else: return map(deep_copy, x)
Это более подходящие для Python
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.Примечание: это не безопасно со списком изменяемых типов
Comments