Hoe kopieer ik een lijst?

Ik heb een probleem met een lijstkopie:

Dus nadat ik E0van 'get_edge'heb gekregen, maak ik een kopie van E0door 'E0_copy = list(E0)'. Hier denk ik dat E0_copyeen diepe kopie is van E0, en ik geef E0_copydoor aan 'karger(E)'. Maar in de hoofdfunctie.
Waarom is het resultaat van 'print E0[1:10]'voor de for-lus niet hetzelfde als dat na de for-lus?

Hieronder staat mijn code:

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

1, Autoriteit 100%

E0_copyis geen diepe kopie. U maakt geen diepe kopie met behulp van list(). (Zowel list(...)en testList[:]zijn ondiepe exemplaren.)

u gebruikt copy.deepcopy(...)voor het kopiëren van een lijst.

deepcopy(x, memo=None, _nil=[])
    Deep copy operation on arbitrary Python objects.

Zie het volgende fragment –

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

Zie nu de deepcopyBediening

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

2, Autoriteit 26%

Ik ben van mening dat veel programmeurs een of twee interviewproblemen hebben uitgevoerd waar ze worden gevraagd om een ​​gekoppelde lijst te kopiëren, maar dit probleem is moeilijker dan het klinkt!

In Python is er een module genaamd “kopie” met twee handige functies

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

Kopiëren () is een ondiepe kopieerfunctie, indien het opgegeven argument een samengestelde gegevensstructuur is, bijvoorbeeld een lijst , dan zal Python een ander voorwerp van hetzelfde type maken (in dit geval, een Nieuwe lijst ) Maar voor alles in de oude lijst, wordt alleen hun referentie gekopieerd

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

Intuïtief kunnen we aannemen dat deepcopy () hetzelfde paradigma zou volgen, en het enige verschil is dat voor elke elem we recursief noemen, deepcopy , (net als het antwoord van MBCODER)

Maar dit is verkeerd!

Deepcopy () behoud daadwerkelijk de grafische structuur van de originele samengestelde gegevens:

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

Dit is het lastige deel, tijdens het proces van deepcopy () een hashtable (Woordenboek in Python) wordt gebruikt om:
“Old_Object Ref op New_Object Ref”, dit voorkomt onnodige duplicaten en behoud dus de structuur van de gekopieerde samengestelde gegevens

officiële doc


3, Autoriteit 7%

Als de inhoud van de lijst primitieve gegevenstypen zijn, kunt u een begrip gebruiken

new_list = [i for i in old_list]

U kunt het nestelen voor multidimensionale lijsten zoals:

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

Antwoord 4

Hier is een voorbeeld van hoe u een 2D-lijst diep kunt kopiëren:

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

Antwoord 5

slechts een recursieve functie voor diep kopiëren.

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

Bewerken: zoals Cfreak al zei, is dit al geïmplementeerd in de module copy.


Antwoord 6

Als u geen modules rechtstreeks mag importeren, kunt u uw eigen deepcopy-functie definiëren als –

def copyList(L):
if type(L[0]) != list:
    return [i for i in L]
else:
    return [copyList(L[i]) for i in range(len(L))]

Het werkt, kan gemakkelijk worden gezien als –

>>> x = [[1,2,3],[3,4]]
>>> z = copyList(x)
>>> x
[[1, 2, 3], [3, 4]]
>>> z
[[1, 2, 3], [3, 4]]
>>> id(x)
2095053718720
>>> id(z)
2095053718528
>>> id(x[0])
2095058990144
>>> id(z[0])
2095058992192
>>>

Antwoord 7

Betreffende de lijst als een boom, kan de deep_copy in python het meest compact worden geschreven als

def deep_copy(x):
    if not isinstance(x, list):
        return x
    else:
        return [deep_copy(elem) for elem in x]

Het is eigenlijk recursief de lijst doorlopen op een diepte-eerst manier.


Antwoord 8

Dit is meer pythonisch

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.

OPMERKING: dit is niet veilig met een lijst met objecten waarnaar wordt verwezen

Other episodes