嵌套集合的OrderBy
本文关键字:OrderBy 集合 嵌套 | 更新日期: 2023-09-27 18:28:31
我正在尝试对这个复杂的对象进行排序:
Order _sut = new Order
{
OrderDataArray = new[]
{
new OrderData
{
OrderHeaderArray = new[]
{
new OrderHeader
{
SequenceNumber = 1,
OrderPositionArray = new[]
{
new OrderPositions
{
LineNumber = 3
},
new OrderPositions
{
LineNumber = 2
},
new OrderPositions
{
LineNumber = 1
}
}
}
}
}
}
};
使用代码:
[Fact]
public void Sorts_By_Sequence_Number()
{
var ordered = _sut.OrderDataArray
.OrderBy(o => o.OrderHeaderArray
.OrderBy(a => a.OrderPositionArray
.OrderBy(p => p.LineNumber)))
.ToArray();
_sut.OrderDataArray = ordered;
OutputHelper(_sut);
}
我不明白为什么这不起作用,这意味着排序例程只是保持LineNumber
对象的初始顺序。我用OrderBy
尝试了各种方法,但看起来不分类。
编辑
感谢您的回复,两者都是正确的。我接受了poke的回应,因为它提供了关于OrderBy方法内部工作的更详细的信息。基本上,我错过了循环中的赋值,我试图同时对所有对象进行排序。
您应该考虑OrderBy
的作用。它根据您在lambda表达式中确定的值对集合进行排序,然后返回一个可枚举值。
你的外线电话很好:
_sut.OrderDataArray.OrderBy(o => something).ToArray();
您按某个东西排序,然后将结果转换为一个(然后排序)数组。这里有两件事很重要:首先,至少在您的示例中,OrderDataArray
中只有一个对象,因此没有排序。其次,它取决于something
的返回值如何对这些对象进行排序。
那么,在这种情况下,什么是something
?如下所示:
o.OrderHeaderArray.OrderBy(a => somethingElse)
那么,不管somethingElse
如何,它会返回什么呢?一个IEnumerable<OrderHeader>
。多个可枚举对象如何相互比较?它们并不是真正可比的;他们尤其不会根据内容告诉你任何关于订单的信息(你必须先列举它)。因此,本质上,你通过"其他东西"对OrderHeaderArray
进行排序,使用没有告诉你任何关于订单的结果作为对OrderDataArray
进行排序的关键。然后,将已排序的OrderHeaderArray
丢弃。
您对OrderPositionArray
做了同样的操作,只需再深入一层,这将不会有任何用处。唯一实际有用的排序发生在OrderPositionArray
本身上,但结果再次被丢弃。
现在,如果您想对结构进行排序,您应该通过将排序后的结构重新组合到数组来正确地进行排序。因此,在某些情况下,您必须执行以下操作:
a.OrderPositionArray = a.OrderPositionArray.OrderBy(p => p.LineNumber).ToArray();
但除了OrderPositionArray
本身和OrderHeader
之外,您实际上没有任何可以排序的东西(因为您不能真正按照子集合的顺序对集合进行排序)。所以你可以这样解决:
foreach (OrderData data in _sut.OrderDataArray)
{
foreach (OrderHeader header in data.OrderHeaderArray)
{
header.OrderPositionArray = header.OrderPositionArray.OrderBy(p => p.LineNumber).ToArray();
}
data.OrderHeaderArray = data.OrderHeaderArray.OrderBy(h => h.SequenceNumber).ToArray();
}
代替Linq,您还可以对数组进行适当的排序,这可能会让它变得更好,因为您没有创建新的内部数组:
var c = Comparer<int>.Default;
foreach (OrderData data in _sut.OrderDataArray)
{
foreach (OrderHeader header in data.OrderHeaderArray)
{
Array.Sort(header.OrderPositionArray, new Comparison<OrderPositions>((x, y) => c.Compare(x.LineNumber, y.LineNumber)));
}
Array.Sort(data.OrderHeaderArray, new Comparison<OrderHeader>((x, y) => c.Compare(x.SequenceNumber, y.SequenceNumber)));
}
此处,
var ordered = _sut.OrderDataArray.OrderBy(o => ...
期望Func<OrderData, TKey>
,并且将通过比较此函数执行的结果来对值进行排序。
同时,传递另一个OrderBy
的结果,即IOrderedEnumerable
。这根本没有多大意义。
为了对所有嵌套集合进行排序,可以执行以下操作:
foreach (var orderData in _sut.OrderDataArray)
{
foreach (var orderHeader in orderData.OrderHeaderArray)
{
orderHeader.OrderPositionArray = orderHeader.OrderPositionArray
.OrderBy(x => x.LineNumber).ToArray();
}
orderData.OrderHeaderArray = orderData.OrderHeaderArray
.OrderBy(x => x.SequenceNumber).ToArray();
}
_sut.OrderDataArray = _sut.OrderDataArray
.OrderBy(x => ...).ToArray();
它根据其项目的LineNumber
对每个OrderPositionArray
项目进行排序
它根据标头的SequenceNumber
对每个OrderHeaderArray
进行排序。
然而,还不清楚您希望如何对_sut.OrderDataArray
进行排序——在示例中,它被标记为x => ...
它没有可用于排序的类似属性。