【问题标题】:Group objects in List<T> by id and order the List by duplicateCount for each object按 id 对 List<T> 中的对象进行分组,并按每个对象的 duplicateCount 对 List 进行排序
【发布时间】:2011-08-05 15:22:34
【问题描述】:

我有多个包含对象的列表。但是一个列表中的某些项目也存在于其他列表中。 我的问题是如何将所有列表中的所有项目合并到一个最终列表中。因此,该列表中没有重复项,并且项目根据每个项目在不同列表中的重复次数进行排序。

例子

列表1:[用户1,用户2,用户3,用户4]
列表 2:[用户 2,用户 4,用户 5]
列表 3:[user4,user6]

结果:[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>();

但结果是一个空列表。

提前致谢!

【问题讨论】:

  • 您能否制作一个简短但完整的程序来显示问题。尝试重现问题会给我你想要的确切列表,所以我敢打赌这是我们没有看到的代码中的东西。
  • 您拥有的代码有效。您的问题出在其他地方。
  • 我的输入列表不为空。在我先尝试 sortedDictionary 之后,我会添加更多代码。

标签: c# linq list sorting group-by


【解决方案1】:

这将按照您的要求工作:

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

【讨论】:

  • @MikeEast 投影应该是 g.Key
  • 奇怪,我希望这个解决方案的性能不如 paulmey 的解决方案,但是,情况正好相反。 (并不是说只要性能不是问题,清晰度就不会赢。)我只是想知道这会编译成哪个比其他解决方案性能更高。
  • @Steven,我不认为有这么大的性能差异。这甚至可能表现得更好。
  • @MikeEast:表现更好。 ;p(至少对于我电脑上的大量收藏)
  • @Steven,我的也是:在示例中对集合进行 1M 次迭代时,4741 毫秒 vs 3467 毫秒。
【解决方案2】:

使用字符串完成,但也应该使用对象:

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

【讨论】:

    【解决方案3】:

    试试这个

    var 结果 = list1.Union(list2).Union(list3).ToList();

    【讨论】:

      猜你喜欢
      • 2012-08-22
      • 1970-01-01
      • 2020-08-03
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多