Gyula Soós
Gyula Soós

Reputation: 487

How to create a new list of objects while removing duplicates?

I got the following code

List<RRProcess> noDuplicates = pSorted
    .GroupBy(i => i.pID)
    .Select(group => group.First())
    .ToList();

The problem is, that if I change anything in the noDuplicates, it will change it in the pSorted as well. I've read all the posts about how the create a new list, but still cant figure it out in my case, how do I have to do it.

So the question is, how do I create a new list, from the elements of pSorted, without duplicating the objects which have the same pID?

thanks

Upvotes: 0

Views: 146

Answers (2)

Peter B
Peter B

Reputation: 24280

You'll need to create new objects if you want to prevent this. There are multiple ways, e.g. use ICloneable, or create new objects yourself.

If your class implements ICloneable:

List<RRProcess> noDuplicates = pSorted
    .GroupBy(i => i.pID)
    .Select(group => (RRProcess) group.First().Clone())
    .ToList();

Or if it has a constructor that allows making a copy from an original:

List<RRProcess> noDuplicates = pSorted
    .GroupBy(i => i.pID)
    .Select(group => new RRProcess(group.First()))
    .ToList();

Or using a parameterless constructor + object initializer:

List<RRProcess> noDuplicates = pSorted
    .GroupBy(i => i.pID)
    .Select(group => group.First())
    .Select(x => new RRProcess { pID = x.pID /* etc for other properties */ } )
    .ToList();

Note that creating a copy - no matter how - can be tricky, e.g. if the original has a collection, you may find that the copied object needs to get a copy of that collection, and not just a new reference to that same old collection. This is called deep cloning. Both can work, it depends on if you need this or not.

Upvotes: 6

Bauss
Bauss

Reputation: 2797

It cannot be done directly in LINQ, it requires some additional code from your side.

If your objects (In this case RRProcess.) doesn't have any members that are objects, then you can implement a clone method for your object like below:

    public RRProcess Clone()
    {
        return this.MemberwiseClone();
    }

I shall note that MemberwiseClone will only produce a shallow clone, hence why it will not clone objects.

In cases where RRProcess implements objects and you need to clone those too then you have to perform a deep clone.

See this answer: https://stackoverflow.com/a/129395/2026276

You can use the above to implement ICloneable see: https://msdn.microsoft.com/en-us/library/system.icloneable(v=vs.110).aspx

However I advice you in your case to implement it without, because Clone() from ICloneable only returns an object which will require further casting from your side and it may not be worth it in your case.

What you can then do is this:

List<RRProcess> noDuplicates = pSorted
    .GroupBy(i => i.pID)
    .Select(group => group.First().Clone())
    .ToList();

If you implement ICloneable

List<RRProcess> noDuplicates = pSorted
    .GroupBy(i => i.pID)
    .Select(group => (RRProcess)group.First().Clone())
    .ToList();

Upvotes: 3

Related Questions