1

我被要求对数据集应用条件排序,我试图弄清楚如何通过 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。出于排序目的,次要采购订单被忽略,但仍应按发货日期降序排列在其主要采购订单下方。

例如,假设用户按送货地址升序排序。数据将按如下方式排序。请注意,如果您忽略辅助采购订单,数据将按地址升序排序(Avery、Fresno、Seattle、Tallahassee)

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
}
4

2 回答 2

3

你见过 ThenBy 和 ThenByDescending 方法吗?

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

我不确定这是否符合您的需求,因为我不太了解最终列表的外观(po.IsPrimary 和 !po.IsPrimary 让我感到困惑)。

于 2009-11-16T15:45:22.450 回答
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 列排序并按主要订单 ID 分组的树状结构。

于 2009-11-16T16:48:14.557 回答