Группируйте объекты в List <T>по id и упорядочивайте список по duplicateCount для каждого объекта - PullRequest
3 голосов
/ 14 апреля 2011

У меня есть несколько List с объектами. Но некоторые элементы в одном списке также существуют в других списках. У меня вопрос, как я могу объединить все элементы всех списков в один окончательный список. Таким образом, в этом списке нет дубликатов, и элементы отсортированы по количеству дубликатов, которые каждый элемент имел в разных списках.

Пример

Список1: [пользователи1, пользователь2, пользователь3, пользователь4]
Список 2: [пользователь2, пользователь4, пользователь5]
Список 3: [пользователь4, пользователь6]

результат: [user4, user2, user1, user3, user5, user6]

(порядок пользователей с таким же количеством не имеет значения)

Я пробовал что-то вроде этого:

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

но результатом является пустой список.

Заранее спасибо!

Ответы [ 3 ]

5 голосов
/ 14 апреля 2011

Это будет работать так, как вы просили:

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;

И версия с объектом вместо строки

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;

Редактировать: Обновлены примеры кода, проецирующие g.Key вместо g.

А вот эквивалент цепочки методов для приведенного выше запроса:

var result = allLists
    .GroupBy(u => u.Name)
    .OrderByDescending(g => g.Count())
    .Select(g => g.Key);
1 голос
/ 14 апреля 2011

Сделано со строками, но также должно работать с объектами:

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);
0 голосов
/ 14 апреля 2011

Попробуйте это

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

...