2015-12-29 60 views
0

我试图解决这复杂的对象:排序依据的嵌套集合

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方法内部运作的更详细信息。基本上我错过了循环内的任务,我试图一次对所有对象进行排序。

+1

你究竟想要排序和按哪些属性? –

回答

1

你应该考虑OrderBy做什么。它按您在lambda表达式中确定的值来排序集合,然后返回一个枚举值。

您的通话外好为:

_sut.OrderDataArray.OrderBy(o => something).ToArray(); 

您排序的东西,然后将结果转换成(当时排序)阵列。有两件事很重要:首先,至少在你的例子中,OrderDataArray中只有一个对象,所以没有排序发生。其次,它取决于something这些对象如何排序的返回值。

那么在那种情况下,什么是something?这是以下情况:

o.OrderHeaderArray.OrderBy(a => somethingElse) 

所以不管somethingElse,这是什么回报呢?一个IEnumerable<OrderHeader>。多个枚举数如何相互比较?他们并没有真正的可比性;他们尤其不会告诉你任何关于基于他们的内容的订单(你必须先列举它)。所以基本上,你通过“别的东西”来订购OrderHeaderArray,使用没有告诉你任何关于订单的结果作为订购OrderDataArray的关键。然后,你把排序后的OrderHeaderArray扔掉。

你完全可以在OrderPositionArray的深度上做同样的操作,它不会做任何有用的操作。唯一实际有用的排序发生在OrderPositionArray本身,但结果再次被丢弃。


现在,如果你想订购的结构,你应该这样做正确,通过reassinging排序的结构数组。所以,在某些时候,你就必须做到以下几点:

a.OrderPositionArray = a.OrderPositionArray.OrderBy(p => p.LineNumber).ToArray(); 

但除了OrderPositionArray本身和OrderHeader,你真的没有任何可以进行排序(因为你不能真正不大不小的按子集合的顺序收集)。所以,你可以可以解决这个问题是这样的:

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))); 
} 

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,您还可以在阵列原地的,这可能使它更好一点,因为你没有创造新的内部数组进行排序

+0

戳,代码中存在一个小错误,例子,而不是Array.Sort(a.OrderPositionArray ...它应该是Array.Sort(header.OrderPositionArray ... – deCoder

+0

哦,你是对的,谢谢,我修好了。 – poke

0

这里,

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(); 

它通过排序每个OrderPositionArray项目列入项目LineNumber
它通过标题'SequenceNumber对每个OrderHeaderArray进行排序。

但是,如何分类_sut.OrderDataArray还不清楚 - 在示例中它被标记为x => ...
它没有可比较的属性可用于排序。

+0

你可能是指'Func '而不是'Action <>'... – haim770