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

问题描述 投票:0回答:5

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

// 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"},
};

然后我用名为

List<Button>
 的按钮类型填充 
mainButtons

这就是我查询分组

Category
的方式:

var categories = from b in mainButtons
                 group b by b.category into g
                 select new { Category = g.Key, Buttons = g };

如何选择主列表中每组的第一项? (无需迭代每个列表并添加到另一个列表?)

c# .net linq
5个回答
109
投票
var result = list.GroupBy(x => x.Category).Select(x => x.First())

82
投票

参见 LINQ:如何使用 group by 子句获取最新/最后一条记录

var firstItemsInGroup = from b in mainButtons
                 group b by b.category into g
select g.First();

我假设 mainButtons 已经正确排序。

如果您需要指定自定义排序顺序,请使用 OrderBy 覆盖 Comparer。

var firstsByCompareInGroups = from p in rows
        group p by p.ID into grp
        select grp.OrderBy(a => a, new CompareRows()).First();

请参阅我的帖子中的示例 “使用自定义比较器选择组中的第一行


31
投票
var results = list.GroupBy(x => x.Category)
            .Select(g => g.OrderBy(x => x.SortByProp).FirstOrDefault());

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

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


5
投票

首先,我不会使用多维数组。只见过不好的事情发生。

像这样设置变量:

IEnumerable<IEnumerable<string>> data = new[] {
    new[]{"...", "...", "..."},
    ... etc ...
};

然后你就可以:

var firsts = data.Select(x => x.FirstOrDefault()).Where(x => x != null); 

如果你有一个空列表作为里面的项目,那么Where可以确保它删除任何空值。

您也可以将其实现为:

string[][] = new[] {
    new[]{"...","...","..."},
    new[]{"...","...","..."},
    ... etc ...
};

这可以类似于

[x,y]
数组使用,但使用方式如下:
[x][y]


0
投票

更新:您可以使用 .NET 6 版本中提供的 DistinctBy 方法:

subButtonData
        .Cast<string>()
        .Chunk(subButtonData.GetLength(1))
        .Select(chunk => new
        {
            Icon = chunk[0],
            Category = chunk[1],
            Tool = chunk[2]
        })
        .DistinctBy(button => button.Category);
© www.soinside.com 2019 - 2024. All rights reserved.