C# – Group objects in List by id and order the List by duplicateCount for each object

cgroup-bylinqlistsorting

I have multiple List with objects. But some of the items in one list, also exists in other lists.
My question is how can I merge all the items of all the lists into one final list. So there are no duplicates in that list and the items are sorted on the number of duplicates each item had in the different lists.

Example

List1: [users1, user2, user3, user4]
List2: [user2, user4, user5]
List3: [user4,user6]

result: [user4, user2, user1, user3, user5, user6]

(the order of users with the same count doesn't matter)

I tried something like this:

List<User> finalResults = list1.Concat(list2).ToList<User>();

        var q = finalResults.GroupBy(x => x.id)
                    .Select(g => new User { name = g.First().name, count = g.Count() })
                    .OrderByDescending(usr => usr.count);

        finalResults = q.ToList<User>();

but the result is an empty list.

Thanks in advance!

Best Answer

This will work like you requested:

var list1 = new[] { "u1", "u2", "u3", "u4" };
var list2 = new[] { "u2", "u4", "u5" };
var list3 = new[] { "u4", "u6" };

var allLists = list1.Concat(list2).Concat(list3);

var result = from u in allLists
             group u by u into g
             orderby g.Count() descending 
             select g.Key;

And a version with an object instead of string

var list1 = new[] { new User("u1"), new User("u2"), new User("u3"), new User("u4") };
var list2 = new[] { new User("u2"), new User("u4"), new User("u5") };
var list3 = new[] { new User("u4"), new User("u6") };

var allLists = list1.Concat(list2).Concat(list3);

var result = from u in allLists
                group u by u.Name into g
                orderby g.Count() descending 
                select g.Key;

Edit: Updated code samples projecting g.Key instead of only g.

And here is the Method Chain equivalent of the query above:

var result = allLists
    .GroupBy(u => u.Name)
    .OrderByDescending(g => g.Count())
    .Select(g => g.Key);