我有以下LINQ查询,它将用于查找“相似”的所有托运货物:

from c in cons
group c by new { c.TripDate.Value, c.DeliveryPostcode, c.DeliveryName } into cg
let min = cg.Min(a => a.DeliverFrom)
let max = cg.Max(a => a.DeliverFrom)
let span = max - min
where span.TotalMinutes <= 59
select cg;


最主要的是最小,最大和跨度。基本上,“组”中任何与组中其他任何货物在59分钟之内具有DeliverFrom日期时间的托运货物都将在组中退回。

上面的代码本来对我来说看起来不错,但经过​​进一步检查,似乎该组中有2条以上的记录-2条记录的DeliverFrom日期彼此间隔59分钟,而一条记录的DeliverFrom日期不在59分钟之内,则该查询将不会返回该组,因为它将选择最小值和最大值,并且发现相差超过59分钟。我想发生的事情是,在该组中有2个托运货物,并且DeliverFrom日期足够接近,然后选择一个包含两个托运货物的组。

我将如何去做呢?

编辑:Doh,在此添加了另一个子句。有一个名为“ Weight”的字段,一个名为“ Spaces”的字段,每个组最多可以有26个Weight和26个Spaces

最佳答案

我将使用与您相同的逻辑将货物分组,但是使用GroupBythis overload代替,这使我可以将每组货物投影到另一种类型。在此,此类型将是一组可枚举的成批物品序列,其中每个元素代表的托运物品不仅应属于同一组,而且还应在一个小时的时间内全部交付。所以resultSelector的签名是

Func<anontype, IEnumerable<Consignment>, IEnumerable<IEnumerable<Consignment>>>


至此,很明显,为分组定义一个类型可能是一个好主意,这样您就可以摆脱上述签名中的匿名类型了。否则,您将不得不将resultSelector定义为lambda。

resultSelector中,首先需要按DeliverFrom对收货的发货组进行排序,然后根据该时间返回子组。因此可能看起来像这样:

IEnumerable<IEnumerable<Consignment>>
Partitioner(ConsignmentGroupKey key, IEnumerable<Consignment> cg)
{
    cg = cg.OrderBy(c => c.DeliverFrom);
    var startTime = cg.First().DeliverFrom;
    var subgroup = new List<Consignment>();

    foreach(var cons in cg) {
        if ((cons.DeliverFrom - startTime).TotalMinutes < 60) {
            subgroup.Add(cons);
        }
        else {
            yield return subgroup;
            startTime = cons.DeliverFrom;
            subgroup = new List<Consignment>() { cons };
        }
    }

    if (subgroup.Count > 0) {
        yield return subgroup;
    }
}


我没有尝试过,但是据我所知它应该可以工作。

10-08 15:51