Достижение сложной сортировки через Linq to Objects

Меня попросили применить условную сортировку к набору данных, и я пытаюсь выяснить, как этого добиться с помощью 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 игнорируются для целей сортировки, но все равно должны быть перечислены ниже их первичного 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 и сгруппированная по первичному идентификатору заказа.

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

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

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

Другие вопросы по тегам