2009-11-16 34 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。次要采购订单在分拣时被忽略,但仍应在发货日期降序下列在主要采购订单下方。

例如,假设用户按送货地址升序排序。数据将按如下排序。请注意,如果你忽略了次要的采购订单,该数据是通过地址升序(艾利,弗雷斯诺,西雅图,塔拉哈西)

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 

有没有办法实现使用排序依据扩展方法预期的效果?或者我坚持(最好)将这种排序应用于两个独立的数据集,然后合并为一个结果集?

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有序列并按主订单ID分组。

+0

棒极了。这与我所需要的非常接近。我仍然需要在每个分组中对ShipDate上的次要事件进行排序。有任何想法吗? – 2009-11-17 16:39:08

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 2009-11-16 15:50:41

+0

我同意,但正如我所说的,对我来说看起来不够清楚,应该如何订购最终名单。所以,我想给他一个关于ThenBy方法的想法,这可能会有所帮助。 – 2009-11-16 16:26:52