LINQ,按属性分组,同时保持其他属性排序

Posted

技术标签:

【中文标题】LINQ,按属性分组,同时保持其他属性排序【英文标题】:LINQ, Group by property while keeping other property sort together 【发布时间】:2021-07-30 03:36:56 【问题描述】:

所以我不完全确定如何解释我在这里尝试做的事情。我正在尝试获取一些数据(由下面的 Excel 文件屏幕截图表示),并且基本上按 Connection2 排序,同时将 Connection1 中的类似项目保持在一起。 (在下面的屏幕截图中进行了解释)

这是我目前所拥有的:

var wires = RedConductorWires
    .OrderBy(x => x.Label)
    .ThenBy(x => x.Connection1)
    .ThenBy(x => x.Connection2)
    .ToList();

正在排序的类对象(匹配 Excel 屏幕截图):

public class CustomExcelFormat

    public string Label  get; set; 
    public string WireSize  get; set; 
    public string WireColor  get; set; 
    public string WirePartNumber  get; set; 
    public string Length  get; set; 
    public string Connection1  get; set; 
    public string Connection1Torque  get; set; 
    public string Connection1Termination  get; set; 
    public string Connection1StripLength  get; set; 
    public string Checkbox1  get; set; 
    public string Connection2  get; set; 
    public string Connection2Torque  get; set; 
    public string Connection2Termination  get; set; 
    public string Connection2StripLength  get; set; 
    public string Checkbox2  get; set; 

屏幕截图:

问题:

问题是,如果您查看屏幕截图,棕色的“A1:TB7:M1”单元格也需要组合在一起,而绿色的“K7:10”需要组合在一起,同时保持它们的 Connection2 排序/组。

换句话说,连接 2 侧,K8:10 和 K8:11 需要保持组合在一起。

所以很明显我的 LINQ 查询不正确,我相信我需要进行某种分组然后排序,但不确定如何处理它,甚至不知道如何准确地提出这个问题(如果有人可以为我说的话)。我基本上需要按连接 2 中的项目分组,同时仍然保持连接 1 排序并放在一起。

如果有人可以为我指出可以执行此类操作的 LINQ 表达式的方向,那就太好了!

编辑

所以我使用了以下查询:

var wires = RedConductorWires
            .OrderBy(x => x.Label)
            .GroupBy(x => new  x.Connection2, x.Connection1 )
            .Select(grp => grp.ToList()).SelectMany(i => i).ToList();

并得到正确的分组。现在我只需要让它按字母顺序排序。见下图。

【问题讨论】:

LINQ 看起来是正确的,并且为自己尝试了连续的ThenBy 调用按预期工作。您确定您将数据正确写入 excel 还是没有以其他方式绊倒您的属性(例如,在您打算使用 Connection1 或类似的地方使用 Connection2 我也举了这个例子,并尝试使用基于您的示例类的内存集合进行重现,并同意 LINQ 查询按预期工作(按标签排序,然后是连接 1,然后是连接 2 )。您如何读取和写入电子表格中的数据? @ahillier88 是的,我链接的 LINQ 查询产生了图片中显示的输出。那就是问题所在。基本上,如果您查看连接 2 列,项目 K8:10,棕色/绿色属性也需要放在一起。我相当确定我需要按连接 2 和 1 进行分组,然后按连接 1 或类似的方式排序? 该表是.OrderBy(x => x.Label).ThenBy(x => x.Connection2).ThenBy(x => x.Connection1) 的结果,而不是您编写的代码。其次,您不能将其按 Connection2 排序并同时将棕色文件分组。第三,一般来说,您甚至不能同时按 Connection2 和 Connection1 对它进行分组。您应该更准确地定义您想要实现的目标。 【参考方案1】:

想象一下这条线

A - B
C - B
C - D
A - D

您可以按照自己喜欢的方式对行重新排序,或者将第一列分组或将第二列分组。但你永远不能同时拥有两者

【讨论】:

查看我的编辑。我得到了它的分组部分,我现在只需要对整个组进行排序。 您的新代码等同于RedConductorWires.OrderBy(x => x.Label).ToList(),因为没有任何组会拥有超过一项。【参考方案2】:

我得到了分组以正确使用以下查询。我决定一开始就按标签排序。

var wires = RedConductorWires
        .OrderBy(x => x.Label)
        .GroupBy(x => new  x.Connection2, x.Connection1 )
        .Select(grp => grp.ToList()).SelectMany(i => i).ToList();

【讨论】:

【参考方案3】:

根据Label, Connection1, Connection2的值分组,然后按这3个字段排序,最终生成所需的输出。

var wires = RedConductorWires
    .GroupBy(a => new  a.Label,a.Connection2, a.Connection1)
    .Join(RedConductorWires,
       left=>new  left.Key.Label,left.Key.Connection1,left.Key.Connection2,
       right => new  right.Label, right.Connection1, right.Connection2 ,
       (left,right)=>new left=left.Key,right = right )
    .OrderBy(x => x.left.Label)
    .ThenBy(x => x.left.Connection2)
    .ThenBy(x => x.left.Connection1)
    .ToList();


foreach(var item in wires)

   Console.WriteLine(item.left.Label + "----" + item.left.Connection1 + "-----" + item.left.Connection2);

 var wires = RedConductorWires
            .OrderBy(x => x.Label)
            .GroupBy(x => new  x.Connection2, x.Connection1 )
            .Select(grp => grp.ToList()).SelectMany(i => i)
            .OrderBy(x => x.Connection2)
            .ThenBy(x => x.Connection1)
            .ToList();

foreach(var item in wires)

   Console.WriteLine(item.Label + "----" + item.Connection1 + "-----" + item.Connection2);

【讨论】:

您的建议根本没有给出正确的输出。不过,请参阅我的编辑,我现在可以进行分组了,我只需要按字母顺序对整个组进行排序。

以上是关于LINQ,按属性分组,同时保持其他属性排序的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中对向量进行分组排序

使用动态 LINQ 按一个或多个属性对 JSON 进行排序

如何按整数属性对类列表进行排序? [复制]

Linq使用多字段分组、排序

如何使用 Matlab 按字母顺序对属性值对进行排序

C# - 使用属性名称作为字符串按属性排序的代码[重复]