Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 基于组计数的排序列表_C#_Linq_Group By - Fatal编程技术网

C# 基于组计数的排序列表

C# 基于组计数的排序列表,c#,linq,group-by,C#,Linq,Group By,我想对列表按I分组s的元素计数进行排序 就这样,理想情况下,列表应该是相同的。我会用一个新的列表来折衷,但是元素应该是完全相同的原始对象,而不是副本(无论多么浅),并且绝对不是匿名对象 特别是:我们有一个具有许多属性的实体,以及这种类型的对象列表。我们希望(1)根据特定属性(名称、地址等)对对象进行分组,然后(2)计算每组中的元素数量。最后,我们希望(3)根据这些计数对列表重新排序,将属于较大组的元素放在第一位 注意:我们的主要问题是,我们似乎找不到在组的元素中保留对原始对象的引用的方法。实际上

我想对
列表
I分组
s的元素计数进行排序

就这样,理想情况下,列表应该是相同的。我会用一个新的列表来折衷,但是元素应该是完全相同的原始对象,而不是副本(无论多么浅),并且绝对不是匿名对象

特别是:我们有一个具有许多属性的实体,以及这种类型的对象列表。我们希望(1)根据特定属性(名称、地址等)对对象进行分组,然后(2)计算每组中的元素数量。最后,我们希望(3)根据这些计数对列表重新排序,将属于较大组的元素放在第一位


注意:我们的主要问题是,我们似乎找不到在组的元素中保留对原始对象的引用的方法。实际上,我们在Linq查询中只能选择分组键(或键的属性),而
igroupping
不会公开任何其他内容。除了查看数据之外,我们也不知道如何将一个组元素与列表中的一个元素相关联(即使这样,我们也需要主键,我们不能将主键添加到分组键中,否则它将破坏分组的初衷)。

在.NET中几乎没有克隆对象的操作。既不深也不浅。LINQ也不会克隆它处理的元素。因此,一个简单的LINQ查询将起作用:

var oldList = ...;
var newList = (from x in oldList
               group x by something into g
               orderby g.Count()
               from x in g //flatten the groups
               select x).ToList();

此代码将引用复制到原始对象。如果你不这么认为,你很可能误解了你所看到的。

好吧,这很尴尬

我的错误确实是基于一个误解:

class Item
{
    internal string Value { get; set; }
    internal string Qux { get; set; }
    internal string Quux { get; set; }
}

var query = from i in list
            group i by new { i.Value, i.Qux } into g // Note: no Quux, no primary key, just what's necessary
            orderby g.Count() descending, g.Key.Value
            select new { // [1]
                Value = g.Key.Value,
                Qux = g.Key.Qux,
                // Quux?
            }
我的错误假设是[1]上的选择作用于单个记录,很像SQL。好吧,希望我能拯救一个有着同样假设的人:事实并非如此

现在看起来很明显,但是选择作用于各个组,因此这里将为每个组创建一个新对象,而不是每个元素

我的第二个错误是把重点放在键上,不知道如何在不使用它的情况下“传递”其他属性。我还担心我们似乎被要求对我们的物品进行肤浅的复制。同样,这是基于这样一个事实,即我们对
i分组
的行为一无所知:因为我们不知道我们在分组上进行选择,所以我们甚至无法从选择中为每个元素创建新对象

解决方案绝对不令人印象深刻:

var query = from i in list
            group i by new { i.Value, i.Qux } into g
            orderby g.Count() descending, g.Key.Value
            select g;

foreach (var group in query)
{
    foreach (var item in group)
        Console.WriteLine("{0} {1} {2} [Original object? {3}]",
            item.Value,
            item.Qux,
            item.Quux,
            list.Contains(item));

    Console.WriteLine("-");
}
输出:

AAA Foo ... [Original object? True]
AAA Foo ... [Original object? True]
AAA Foo ... [Original object? True]
-
BBB Foo ... [Original object? True]
BBB Foo ... [Original object? True]
-
AAA Bar ... [Original object? True]
-
CCC Foo ... [Original object? True]
-
DDD Foo ... [Original object? True]
-
DDD Bar ... [Original object? True]
-
EEE Foo ... [Original object? True]
实际上,
i分组
元素就是原始元素。从那里我们可以创建一个没有任何问题的新列表

更新:我在查询外部展平结果集,主要是为了能够将组分隔符写入控制台进行演示,但请参阅Tim和usr的答案,以便在查询内部使用
SelectMany
(以及等效的Linq语法)展平

不用说,这是另一个经典案例,“我们太匆忙了,让我们到处看看例子,就这样吧”,正确的方法是花一点时间学习基本原理。Linq不是SQL


我很抱歉,你可能浪费了时间试图消除混乱。希望其他人现在能从这些错误中获益。

与其写文本,不如写一个带有示例属性的示例类,然后告诉我们,您希望按哪些属性分组,以及最终选择的顺序您可能缺少的是,您的
i分组实际上也是该组中项目的可枚举项。因此,一旦您对分组进行了排序,您只需再次将项目平铺到一个列表中即可。@ManishMishra:我个人认为这里不需要类。实际上,该问题适用于任何具有单个属性的类。添加这些代码会有什么好处呢?给出精确的场景,使用类似的代码副本,可以减少猜测工作,并且可以为直接编写工作代码注入兴奋。此外,c#比英语更吸引我。非常感谢你的评论,考虑到问题中的混乱,他们出人意料地提供了帮助。我在另一个回答中解释说,这确实是我的一个重大而根本的误解。希望你已经看到了Tim S.生成排序列表的简洁方法。考虑到任务听起来有多么复杂,它的整洁程度令人惊讶。:)的确,我以前不太熟悉
SelectMany
。实际上,usr的答案基本相同,他的代码也被翻译成了
SelectMany
。这是一些快速学习。尽管如此,我还是应该做一个更好的初步努力。我对查询语法不太熟悉,个人认为它看起来不太可读,这就是我提到Tim的原因。但只要你学会了一些东西,那么一切都是值得的
var mySortedList = myList.GroupBy(x => x.Name).OrderByDescending(g => g.Count())
                       .SelectMany(x => x).ToList();