it-swarm.dev

كيفية نسخ قائمة عميقة؟

لدي بعض المشاكل في نسخة القائمة:

لذلك بعد أن حصلت على 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
94
Shen

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]]
164
Sukrit Kalra

أعتقد أن الكثير من المبرمجين واجهوا مشكلة في مقابلة أو اثنتين حيث يُطلب منهم نسخ نسخة متعمقة من قائمة مرتبطة ، لكن هذه المشكلة ليست سهلة كما تبدو!

في الثعبان ، هناك وحدة تسمى "نسخة" مع وظيفتين مفيدتين

import copy
copy.copy()
copy.deepcopy()

copy () هي وظيفة نسخ ضحلة ، إذا كانت الوسيطة المعطاة عبارة عن بنية بيانات مركبة ، على سبيل المثال list ، ثم يقوم python بإنشاء كائن آخر من نفس النوع (في هذه الحالة ، قائمة جديدة ) ولكن لكل شيء داخل القائمة القديمة ، يتم نسخ مرجعهم فقط

# 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 to new_object ref" ، وهذا يمنع التكرارات غير الضرورية وبالتالي الحفاظ على بنية البيانات المركبة المنسوخة

وثيقة رسمية

44
watashiSHUN

إذا كانت محتويات القائمة هي أنواع بيانات بدائية ، يمكنك استخدام الفهم

new_list = [i for i in old_list]

يمكنك تداخلها لقوائم متعددة الأبعاد مثل:

new_grid = [[i for i in row] for row in grid]
7
aljgom

مجرد وظيفة نسخة عميقة عودية.

def deepcopy(A):
    rt = []
    for elem in A:
        if isinstance(elem,list):
            rt.append(deepcopy(elem))
        else:
            rt.append(elem)
    return rt

تحرير: كما ذكر Cfreak ، تم تنفيذ هذا بالفعل في copy module.

2
rnbguy

إذا كان list elements الخاص بك immutable objects ، فيمكنك استخدام هذا ، وإلا يتعين عليك استخدام deepcopyمن الوحدة النمطية copyname__.

يمكنك أيضًا استخدام أقصر الطرق للنسخ العميقة مثل listname__.

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]
2
tailor_raj

فيما يتعلق بالقائمة كشجرة ، يمكن أن تكون النسخة العميقة في الثعبان مكتوبة بشكل مضغوط كـ

def deep_copy(x):
    if not isinstance(x, list): return x
    else: return map(deep_copy, x)
1
ShellayLee