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,按属性分组,同时保持其他属性排序的主要内容,如果未能解决你的问题,请参考以下文章