开发者

Group objects in List<T> by id and order the List by duplicateCount for each object

开发者 https://www.devze.com 2023-02-25 01:28 出处:网络
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

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!


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);


Done with strings, but should also work with objects:

var l = new string[] { "user1", "user2", "user3", "user4",
    "user2", "user4", "user5" ,
    "user4", "user6" };

var result = l.Aggregate(new Dictionary<string, int>(),
    (res, user) =>
    { // create a dictionary of all users and their occurence
        if (!res.ContainsKey(user)) res[user] = 0;
        res[user]++;
        return res;
    }).OrderByDescending(kvp => kvp.Value) // order by incidence
    .Select(kvp => kvp.Key); // select user names only

foreach (var user in result) Console.WriteLine(user);


Try This

var result = list1.Union(list2).Union(list3).ToList();

0

精彩评论

暂无评论...
验证码 换一张
取 消