2009-11-16 1 views
1

Меня попросили применить условную сортировку к набору данных, и я пытаюсь выяснить, как достичь этого через LINQ. В этом конкретном домене заказы на покупку могут быть помечены как первичные или вторичные. Точный механизм, используемый для определения первичного/вторичного статуса, довольно сложный и не связан с проблемой.Достижение сложной сортировки через Linq для объектов

Рассмотрите приведенные ниже данные.

Purchase Order Ship Date  Shipping Address  Total 
6     1/16/2006  Tallahassee FL  500.45 
19.1    2/25/2006  Milwaukee WI  255.69 
5.1    4/11/2006  Chicago IL   199.99 
8     5/16/2006  Fresno CA   458.22 
19    7/3/2006  Seattle WA   151.55 
5     5/1/2006  Avery UT   788.52  
5.2     8/22/2006  Rice Lake MO  655.00 

Вторичные PO - это те, у которых есть десятичное число, а первичные PO - это целые числа. Требование, которое я имею в виду, гласит, что, когда пользователь выбирает сортировку по данному столбцу, сортировка должна быть только применяется к первичным PO. Вторичные PO-адреса игнорируются для целей сортировки, но все же должны быть перечислены ниже их основного ПО в порядке убывания даты отправки.

Например, пользователь сортируется по адресу доставки по возрастанию. Данные будут отсортированы следующим образом. Обратите внимание, что если вы игнорируете вторичный ДДУ данные сортируются по возрастанию Адрес (Avery, Фресно, Сиэтл, Таллахасси)

Purchase Order  Ship Date  Shipping Address  Total 
5     5/1/2006  Avery UT   788.52 
--5.2    8/22/2006  Rice Lake MO  655.00 
--5.1    4/11/2006  Chicago IL   199.99 
8     5/16/2006  Fresno CA   458.22 
19     7/3/2006  Seattle WA   151.55 
--19.1    2/25/2006  Milwaukee WI  255.69 
6     1/16/2006  Tallahassee FL  500.45 

Есть ли способ, чтобы достичь желаемого эффекта с помощью метода расширения OrderBy? Или я застрял (лучше), применяя сортировку к двум наборам данных независимо, а затем объединившись в один набор результатов?

public IList<PurchaseOrder> ApplySort(bool sortAsc) 
{ 
    var primary = purchaseOrders.Where(po => po.IsPrimary) 
           .OrderBy(po => po.ShippingAddress).ToList(); 
    var secondary = purchaseOrders.Where(po => !po.IsPrimary) 
            .OrderByDescending(po => po.ShipDate).ToList(); 
    //merge 2 lists somehow so that secondary POs are inserted after their primary 
} 

ответ

2

Решение проблемы: GroupBy.

Первый заказ ваш объект в соответствии с выбранной колонки:

var ordered = purchaseOrders.OrderBy(po => po.ShippingAddress); 

Чем вам нужно сгруппировать заказы по основному заказу. Я предположил, порядок является строкой, поэтому я создал строку IEqualityComparer следующим образом:

class OrderComparer : IEqualityComparer<string> 
{ 
    public bool Equals(string x, string y) 
    { 
     x = x.Contains('.') ? x.Substring(0, x.IndexOf('.')) : x; 
     y = y.Contains('.') ? y.Substring(0, y.IndexOf('.')) : y; 

     return x.Equals(y); 
    } 

    public int GetHashCode(string obj) 
    { 
     return obj.Contains('.') ? obj.Substring(0, obj.IndexOf('.')).GetHashCode() : obj.GetHashCode(); 
    } 
} 

и использовать его, чтобы сгруппировать заказы:

var grouped = ordered.GroupBy(po => po.Order, new OrderComparer()); 

Результатом является дерево, как структура по заказу ShippingAddress столбца и сгруппированы по первому идентификатору заказа.

+0

Превосходно. Это очень близко к тому, что мне нужно. Мне все еще нужно сортировать вторичные события на ShipDate в каждой группе. Есть идеи? –

3

Вы видели методы ThenBy и ThenByDescending?

purchaseOrders.Where(po => po.IsPrimary).OrderBy(po => po.ShippingAddress).ThenByDescending(x=>x.ShipDate).ToList(); 

Я не уверен, если это будет соответствовать вашим потребностям, потому что я не тихий хорошо понять, как окончательный список должен выглядеть (po.IsPrimary и! Po.IsPrimary сбивает с толку меня).

+0

Я не думаю, что это ответ. 'ThenBy' будет работать, только если более одного значения' Order' будут равны. – HuBeZa

+0

Я согласен, но, как я уже сказал, не выглядит достаточно ясным для меня, как следует заказывать окончательный список. Поэтому я хотел дать ему представление о методе ThenBy, который может помочь. –