Equalsk Equalsk - 1 year ago 59
C# Question

How can I split a List<T> into two lists, one containing all duplicate values and the other containing the remainder?

I have a basic class for an Account (other properties removed for brevity):

public class Account
public string Email { get; set; }

I have a
of these accounts.

I can remove duplicates based on the e-mail address easily:

var uniques = list.GroupBy(x => x.Email).Select(x => x.First()).ToList();

The list named 'uniques' now contains only one of each account based on e-mail address, any that were duplicates were discarded.

I want to do something a little different and split the list into two.

One list will contain only 'true' unique values, the other list will contain all duplicates.

For example the following list of Account e-mails:




Would be split into two lists:






I have been able to achieve this already by creating a list of unique values using the example at the top. I then use
on the original list to get the differences which are the duplicates. Lastly I can loop over each duplicate to 'pop' it out of the unique list and move it to the duplicate list.

Here is a working example on .NET Fiddle

Can I split the list in a more efficient or syntactically sugary way?

I'd be happy to use a third party library if necessary but I'd rather just stick to pure LINQ.

I'm aware of CodeReview but feel the question also fits here.

Answer Source
var duplicates = list.GroupBy(x => x) // or x.Property if you are grouping by some property.
                     .Where(g => g.Count() > 1)
                     .SelectMany(g => g);

var uniques = list.GroupBy(x => x) // or x.Property if you are grouping by some property.
                  .Where(g => g.Count() == 1)
                  .SelectMany(g => g);
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download