C# Linq查询分组依据并选择第一项

C# Linq查询分组依据并选择第一项,c#,.net,linq,C#,.net,Linq,我有一个类似这样的字符串数组: // icon, category, tool String[,] subButtonData = new String[,] { {"graphics/gui/brushsizeplus_icon", "Draw", "DrawBrushPlus"}, {"graphics/gui/brushsizeminus_icon", "Draw", "DrawBrushMinus"}, {"graphics/gui/freedraw_icon",

我有一个类似这样的字符串数组:

// icon, category, tool
String[,] subButtonData = new String[,]
{
    {"graphics/gui/brushsizeplus_icon", "Draw", "DrawBrushPlus"},
    {"graphics/gui/brushsizeminus_icon", "Draw", "DrawBrushMinus"},
    {"graphics/gui/freedraw_icon", "Draw", "DrawFree"},
    {"graphics/gui/linedraw_icon", "Draw", "DrawLine"},
    {"graphics/gui/rectangledraw_icon", "Draw", "DrawRectangle"},
    {"graphics/gui/ellipsedraw_icon", "Draw", "DrawEllipse"},
    {"graphics/gui/brushsizeplus_icon", "Brusher", "BrusherBrushPlus"},
    {"graphics/gui/brushsizeminus_icon", "Brusher", "BrusherBrushMinus"},
    {"graphics/gui/brushsizeplus_icon", "Text", "TextBrushPlus"},
    {"graphics/gui/brushsizeminus_icon", "Text", "TextBrushMinus"},
};
IEnumerable<IEnumerable<string>> data = new[] {
    new[]{"...", "...", "..."},
    ... etc ...
};
然后我用名为mainButtons的按钮类型填充一个列表

以下是我查询类别分组的方式:


如何在主列表中选择每组的第一项?如果不逐一迭代并添加到另一个列表中?

首先,我不会使用多维数组。只有看到坏事情发生的时候

按如下方式设置变量:

// icon, category, tool
String[,] subButtonData = new String[,]
{
    {"graphics/gui/brushsizeplus_icon", "Draw", "DrawBrushPlus"},
    {"graphics/gui/brushsizeminus_icon", "Draw", "DrawBrushMinus"},
    {"graphics/gui/freedraw_icon", "Draw", "DrawFree"},
    {"graphics/gui/linedraw_icon", "Draw", "DrawLine"},
    {"graphics/gui/rectangledraw_icon", "Draw", "DrawRectangle"},
    {"graphics/gui/ellipsedraw_icon", "Draw", "DrawEllipse"},
    {"graphics/gui/brushsizeplus_icon", "Brusher", "BrusherBrushPlus"},
    {"graphics/gui/brushsizeminus_icon", "Brusher", "BrusherBrushMinus"},
    {"graphics/gui/brushsizeplus_icon", "Text", "TextBrushPlus"},
    {"graphics/gui/brushsizeminus_icon", "Text", "TextBrushMinus"},
};
IEnumerable<IEnumerable<string>> data = new[] {
    new[]{"...", "...", "..."},
    ... etc ...
};
Where确保,如果您在其中有一个空列表作为项目,它将删除任何空值

或者,您可以将其实现为:

string[][] = new[] {
    new[]{"...","...","..."},
    new[]{"...","...","..."},
    ... etc ...
};
这可以类似于[x,y]数组,但它的用法如下:[x][y]

请参见

我假设主按钮已经正确排序

如果需要指定自定义排序顺序,请使用OrderBy override with Comparer

var firstsByCompareInGroups = from p in rows
        group p by p.ID into grp
        select grp.OrderBy(a => a, new CompareRows()).First();
在我的帖子中看到一个例子

对于那些想知道如何对不一定正确排序的组执行此操作的人,这里有一个扩展,它使用方法语法自定义每个组的排序顺序,从而从每个组中获得所需的记录


注意:如果使用LINQ to Entities,如果在此处使用First而不是FirstOrDefault,则会出现运行时异常,因为前者只能用作最终查询操作。

为什么您的查询使用与示例集合不同的内容?如果您在.Net 4上,使用IEnumerable甚至会更轻松,这样您就可以确保我总是有三件东西。对于早期的.Net版本,您甚至可以努力创建自己的元组类,或者从internet上选择它。我对.Net 4中的元组感到非常兴奋,但我发现,在使用它们时,冗长会给它们带来更多的麻烦。特别是当您有复杂的元组时:元组在代码中重复了几个地方,很快就会过时。只要您必须拼写出您的类型,您就完全正确了。在大多数情况下?cases Tuple.Create做得很好,因为c为您推断类型。尽管如此,我还是很少使用元组,因为它们很难描述Item1是什么???。在公共API中,它们应该被法律禁止。从EF 6.0开始,如果您在第一次查询后尝试执行任何其他操作,例如选择列的子集,则这将不起作用-您需要使用x.FirstOrDefault,否则您将得到“第一个只能用作最终操作例外”的结果。谢谢,我发现这很有用。我只建议使用FirstOrDefault而不是First来避免可能的运行时错误。@Technoman 23,这取决于您的数据。若您知道数组/列表至少有一个元素,那个么第一个元素更合适,若发生意外的运行时异常,那个么最好尽早失败。如果你的数组/列表可以为空,你应该使用FirstOrDefault并检查返回的变量是否为null。IEnumerable可以正常工作,但如何将其应用于IQueryable?!对于IQueryable,它给了我一个错误:System.InvalidOperationException。OrderByDowninga=>a.Amount'不能为空translated@AhmedAbdElmoniem,我建议您开始一个新问题,详细描述您的问题,包括您使用的代码示例和链接提供程序,例如EntityFramework。欢迎你提及这个问题。许多人可以看到新的问题,他们可以帮助Mr@Michaelfreedgeim,谢谢你的建议,我在这里发布了这个问题:
var firstsByCompareInGroups = from p in rows
        group p by p.ID into grp
        select grp.OrderBy(a => a, new CompareRows()).First();
var result = list.GroupBy(x => x.Category).Select(x => x.First())
var results = list.GroupBy(x => x.Category)
            .Select(g => g.OrderBy(x => x.SortByProp).FirstOrDefault());