2015-12-29 3 views
0

Я пытаюсь разобраться в этом сложный объект:OrderBy на вложенные коллекции

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, но похоже, что он не сортирует.

EDIT

Спасибо за ответы, как правильно. Я принял ответ poke, поскольку он дает немного более подробную информацию о внутренней работе метода OrderBy. В основном я отсутствовал в цикле, я пытался сортировать все объекты сразу.

+1

Что именно вы хотите отсортировать и по каким свойствам? –

ответ

1

Вы должны рассмотреть, что делает OrderBy. Он упорядочивает коллекцию по значению, которое вы определяете в выражении лямбда, а затем возвращает перечислимый.

Ваш внешний вызов хорош для этого:

_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, вы на самом деле не имеют ничего, что может быть отсортирован (потому что вы не можете на самом деле своего рода коллекции по заказу субколлекции). Таким образом, вы могли бы можно было решить, как это:

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

poke, в коде есть небольшая ошибка, а вместо 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.
Сортирует каждый OrderHeaderArray по заголовкам 'SequenceNumber.

Однако, это довольно непонятно, как вы хотите сортировать _sut.OrderDataArray - в этом примере обозначен как x => ....
У него нет сопоставимых свойств, которые можно использовать для сортировки.

+0

Вы, вероятно, имели в виду 'Func ' вместо 'Action <>' ... – haim770

Смежные вопросы