কিভাবে একটি তালিকা গভীর অনুলিপি?


149

একটি তালিকা অনুলিপি নিয়ে আমার কিছু সমস্যা আছে:

আমার E0কাছ থেকে আসার পরে 'get_edge', আমি E0কল করে একটি অনুলিপি তৈরি করি 'E0_copy = list(E0)'। এখানে আমি অনুমান E0_copyগভীর কপি E0, এবং আমি পাস E0_copyমধ্যে 'karger(E)'। তবে মূল ফাংশনে।
কেন 'print E0[1:10]'লুপের আগে লুপের আগে ফলাফল একই রকম হয় না?

নীচে আমার কোডটি দেওয়া হয়েছে:

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

2
এছাড়াও, খ = ক [:] হ'ল একটি অগভীর অনুলিপি। স্ট্যাকওভারফ্লো.com
অরবিন্দ

উত্তর:


229

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

3
ধন্যবাদ। তবে আমি ভেবেছিলাম তালিকা () আইডি (E0) আইডি (E0_copy) এর সমান নয় বলে একটি গভীর অনুলিপি। কেন আপনি তা ব্যাখ্যা করতে পারেন?
শেন

14
তালিকা (...) পুনরাবৃত্তভাবে অভ্যন্তরীণ বস্তুগুলির অনুলিপি তৈরি করে না। এটি কেবল বহিরাগত তালিকার একটি অনুলিপি তৈরি করে, পূর্ববর্তী ভেরিয়েবল থেকে অভ্যন্তরীণ তালিকাগুলি উল্লেখ করার সময়, যখন আপনি অভ্যন্তরীণ তালিকাগুলি পরিবর্তন করেন, পরিবর্তনটি মূল তালিকা এবং অগভীর অনুলিপি উভয়তেই প্রতিফলিত হয়।
সুকৃত কালরা

1
আপনি দেখতে পাচ্ছেন যে অগভীর অনুলিপিটি অভ্যন্তরীণ তালিকাগুলি রেফারেন্স করে সেই আইডি (এ [0]) == আইডি (বি [0]) যেখানে বি = তালিকা (ক) এবং এ তালিকার একটি তালিকা a
সুকৃত কালরা

list1.append (list2) এছাড়াও তালিকা 2 এর অগভীর অনুলিপি
Lazik

60

আমি বিশ্বাস করি যে প্রচুর প্রোগ্রামাররা একটি বা দুটি সাক্ষাত্কারের সমস্যায় ডুবে গেছে যেখানে তাদের লিঙ্কযুক্ত তালিকার গভীর অনুলিপি করতে বলা হয়, তবে এই সমস্যাটি যা মনে হয় তার থেকে কঠিন!

পাইথনে, দুটি কার্যকর ফাংশন সহ "কপি" নামে একটি মডিউল রয়েছে

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

অনুলিপি একটি অগভীর অনুলিপি ফাংশন, যদি প্রদত্ত যুক্তিটি যৌগিক ডেটা কাঠামো হয়, উদাহরণস্বরূপ একটি তালিকা , তবে পাইথন একই ধরণের আরেকটি অবজেক্ট তৈরি করবে (এই ক্ষেত্রে, একটি নতুন তালিকা ) তবে পুরানো তালিকার ভিতরে থাকা সমস্ত কিছুর জন্য, শুধুমাত্র তাদের রেফারেন্স অনুলিপি করা হয়

# think of it like
newList = [elem for elem in oldlist]

স্বজ্ঞাতভাবে, আমরা ধরে নিতে পারি যে ডিপকপি () একই দৃষ্টান্ত অনুসরণ করবে, এবং কেবলমাত্র পার্থক্য হ'ল প্রতিটি এলমের জন্য আমরা পুনরাবৃত্তভাবে ডিপকপি ডাকব , (এমবিকোডারের উত্তরের মতো)

তবে এটা ভুল!

ডিপকপি () আসলে মূল যৌগিক তথ্যের গ্রাফিকাল কাঠামো সংরক্ষণ করে:

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'']

এটি জটিল অংশ, ডিপকপি প্রক্রিয়া চলাকালীন () একটি হ্যাশটেবল (পাইথনের অভিধান) ম্যাপ ব্যবহার করতে ব্যবহৃত হয়: "পুরানো_জেক্ট রেফ নিউ নিউজ রেফের উপর", এটি অপ্রয়োজনীয় সদৃশগুলি প্রতিরোধ করে এবং এভাবে অনুলিপিযুক্ত যৌগিক তথ্যের কাঠামো সংরক্ষণ করে

সরকারী ডক


18

তালিকার বিষয়বস্তুগুলি যদি প্রাথমিক তথ্য প্রকারের হয় তবে আপনি একটি উপলব্ধি ব্যবহার করতে পারেন

new_list = [i for i in old_list]

আপনি এটি বহুমাত্রিক তালিকার জন্য নীড় করতে পারেন:

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

5

যদি আপনার list elementsহয় immutable 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]

21
এটি কোনও গভীর অনুলিপি নয়।
সুকৃত কালরা

1
তাহলে এটা কি. এর দুটি পৃথক অভিধান রয়েছে (আপনি প্রতিটিটির আইডি পরীক্ষা করতে পারেন) একই মান সহ।
দর্জি_রাজ

পড়ুন এই , [:] শুধু একটি অগভীর কপি তৈরি করে, এটা recursively এক ভিতরে অবজেক্টের কপি তৈরি করে না।
সুকৃত কালরা

1
ধন্যবাদ। আপনি বলতে চাইছেন যে আমরা যদি এটি ব্যবহার করি তবে নতুন তালিকা তৈরি হবে তবে নতুন তালিকার সমস্ত উপাদানগুলি কেবল অনুলিপি হবে, তাদের পূর্ববর্তীটির মতো একই বস্তু (একই আইডি) থাকবে?
দর্জি_রাজ

নেস্টেড তালিকা ব্যবহার করে দেখুন। তালিকার নেস্টেড আইটেমটি আপডেট করুন a। এটি তালিকা বিতেও আপডেট হবে। এটি বোঝায় যে একটি [:] গভীর অনুলিপি নয়।
অনুপমচুগ

2

কেবল একটি পুনরাবৃত্ত ডিপ কপি ফাংশন।

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

সম্পাদনা: Cfreak যেমন উল্লেখ করেছে, এটি ইতিমধ্যে copyমডিউলে প্রয়োগ করা হয়েছে ।


4
মডিউলে স্ট্যান্ডার্ড deepcopy()ফাংশনটি পুনরায় প্রয়োগ করার কোনও কারণ নেইcopy
Cfreak

1

গাছ হিসাবে তালিকাগুলি সম্পর্কিত, পাইথনের গভীর_কপিটি সবচেয়ে সংক্ষিপ্তভাবে লেখা যেতে পারে

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

0

কীভাবে একটি তালিকা গভীরভাবে অনুলিপি করতে হবে তার একটি উদাহরণ:

  b = [x[:] for x in a]

0

এটি বেশি পাইথোনিক

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.

দ্রষ্টব্য: রেফারেন্সযুক্ত বস্তুর তালিকার সাথে এটি নিরাপদ নয়


2
এটা কাজ করে না. আমি ভেবেছিলাম এটি কেবল একটি চেকড তবে। একটি ভাল উদাহরণ হিসাবে অভিধানের তালিকা দিয়ে চেষ্টা করুন
শশাঙ্ক সিং

@ শশাঙ্কসিংহ হ্যাঁ এটি অভিধানের তালিকার জন্য কাজ করবে না কারণ এন্ট্রিগুলি রেফারেন্স ট্যাগ (একটি স্মৃতি অবস্থানের দিকে নির্দেশ করে)। সুতরাং সদৃশ এই পদ্ধতির সাথে অভিধানের একটি তালিকা একটি নতুন তালিকা তৈরি করবে তবে এন্ট্রি অভিধান হিসাবে তারা এখনও একই মেমরির অবস্থানটি উল্লেখ করবে।
Kwaw Annor
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.