Deep Copy of List<T>

How create a new deep copy (clone) of a ListT?

You need to create new Book objects then put those in a new List:

List<Book> books_2 = books_1.Select(book => new Book(book.title)).ToList();

Update: Slightly simpler... List<T> has a method called ConvertAll that returns a new list:

List<Book> books_2 = books_1.ConvertAll(book => new Book(book.title));

Deep copy of ListT

The idiomatic way to approach this in C# is to implement ICloneable on your Data, and write a Clone method that does the deep copy (and then presumably a Enumerable.CloneRange method that can clone part of your list at once.) There isn't any built-in trick or framework method to make it easier than that.

Unless memory and performance are a real concern, I suggest that you try hard to redesign it to operate on immutable Data objects, though, instead. It'll wind up much simpler.

Is there any better deep clone methods for list?

That's not a real deep-copy because the Card instances are still the same, only the list is different. You could have this much simpler:

List<Card> cloneList = cards.ToList();

You need to "copy" all properties of the Card instances as well:

public List<Card> Copy(List<Card> cards)
{
List<Card> cloneList = new List<Card>();
foreach (var card in cards)
{
Card clone = new Card();
clone.Property1 = card.Property1;
// ... other properties
cloneList.Add(clone);
}
return cloneList;
}

You could also provide a factory method that creates a clone of a given Card instance:

public class Card
{
// ...

public Card GetDeepCopy()
{
Card deepCopy = new Card();
deepCopy.Property1 = this.Property1;
// ...
return deepCopy;
}
}

Then you have encapsulated this logic in one place where you can even access private members(fields, properties, constructors). Change the line in the Copy method above to:

cloneList.Add(card.GetDeepCopy()); 

How to deep copy a list?

E0_copy is not a deep copy. You don't make a deep copy using list(). (Both list(...) and testList[:] are shallow copies.)

You use copy.deepcopy(...) for deep copying a list.

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

See the following snippet -

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

Now see the deepcopy operation

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

To explain, list(...) does not recursively make copies of the inner objects. It only makes a copy of the outermost list, while still referencing the same inner lists, hence, when you mutate the inner lists, the change is reflected in both the original list and the shallow copy. You can see that shallow copying references the inner lists by checking that id(a[0]) == id(b[0]) where b = list(a).

deep copy of list in python

Your code does indeed succeed in creating a shallow copy. This can be seen by inspecting the IDs of the two outer lists, and noting that they differ.

>>> id(l)
140505607684808

>>> id(x)
140505607684680

Or simply comparing using is:

>>> x is l
False

However, because it is a shallow copy rather than a deep copy, the corresponding elements of the list are the same object as each other:

>>> x[0] is l[0]
True

This gives you the behaviour that you observed when the sub-lists are appended to.

If in fact what you wanted was a deep copy, then you could use copy.deepcopy. In this case the sublists are also new objects, and can be appended to without affecting the originals.

>>> from copy import deepcopy

>>> l=[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

>>> xdeep = deepcopy(l)

>>> xdeep == l
True

>>> xdeep is l
False <==== A shallow copy does the same here

>>> xdeep[0] is l[0]
False <==== But THIS is different from with a shallow copy

>>> xdeep[0].append(10)

>>> print(l)
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

>>> print(xdeep)
[[1, 2, 3, 10], [4, 5, 6], [7, 8, 9]]

If you wanted to apply this in your function, you could do:

from copy import deepcopy

def processed(matrix,r,i):
new_matrix = deepcopy(matrix)
new_matrix[r].append(i)
return new_matrix

l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
x = processed(l,0,10)
print(x)
print(l)

If in fact you know that the matrix is always exactly 2 deep, then you could do it more efficiently than using deepcopy and without need for the import:

def processed(matrix,r,i):
new_matrix = [sublist[:] for sublist in matrix]
new_matrix[r].append(i)
return new_matrix

l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
x = processed(l,0,10)
print(x)
print(l)

How do I clone a generic list in C#?

You can use an extension method.

static class Extensions
{
public static IList<T> Clone<T>(this IList<T> listToClone) where T: ICloneable
{
return listToClone.Select(item => (T)item.Clone()).ToList();
}
}

How to make a deep copy of an object with a List variable in Java?

Your copy constructors are just doing shallow copies of each field. That's fine for strings because they're immutable, and it's fine for ints because they're primitive (which means they lack identity and are immutable). In those cases, there is no important difference between shallow and deep copies. But it doesn't work in general for lists because lists can be mutable and so can their elements. So instead of just pointing at the same list, you need to make a new list and deep copy each element of the original list into the new one.

Use this helper method to make deep copies of any lists:

static <T> List<T> deepCopyList(List<T> list, UnaryOperator<T> deepCopyElement) {
return list.stream().map(deepCopyElement).collect(
Collectors.toCollection(ArrayList::new)
);
}

Like so:

public AtomDTO(AtomDTO that) {
this(that.getName(), that.getType(), deepCopyList(that.getBonds(), BondDTO::new));
}

how to make a deep copy of my list

You can create an extension method where you serialize the object only to deserialize it again. This will create a new object with it's own references, thus a Deep Copy.

Public Module Extensions
<System.Runtime.CompilerServices.Extension()> _
Public Function DeepCopy(Of T)(ByVal Obj As T) As T
If Obj.GetType().IsSerializable = False Then Return Nothing

Using MStream As New MemoryStream
Dim Formatter As New BinaryFormatter
Formatter.Serialize(MStream, Obj)
MStream.Position = 0
Return DirectCast(Formatter.Deserialize(MStream), T)
End Using
End Function
End Module

Now you can just call:

Dim network As List(Of train) = per_network.DeepCopy()

EDIT:

These are the required imports for my code above:

Imports System.IO
Imports System.Runtime.Serialization.Formatters.Binary


Related Topics



Leave a reply



Submit