You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何对已排序的C# List<Order>按连续相同的DeliveryPerson进行分组

实现连续相同DeliveryPerson的Order分组

这个需求用C#标准库的GroupBy是搞不定的——因为它会把所有DeliveryPerson相同的订单都归到同一组,完全不管它们在原列表里是不是连续的。下面给你两种实用的实现方式,都是基于IEnumerable的,兼顾效率和灵活性:

方法一:自定义扩展方法(推荐)

写一个通用的扩展方法,以后任何需要连续分组的场景都能复用。这个方法用懒加载的IEnumerable实现,不用一次性把所有数据都加载到内存,性能更优:

public static class EnumerableExtensions
{
    public static IEnumerable<IEnumerable<T>> GroupConsecutiveBy<T, TKey>(this IEnumerable<T> source, Func<T, TKey> keySelector)
        where TKey : IEquatable<TKey>
    {
        if (source == null) throw new ArgumentNullException(nameof(source));
        if (keySelector == null) throw new ArgumentNullException(nameof(keySelector));

        using var enumerator = source.GetEnumerator();
        if (!enumerator.MoveNext())
            yield break;

        var currentKey = keySelector(enumerator.Current);
        var currentGroup = new List<T> { enumerator.Current };

        while (enumerator.MoveNext())
        {
            var item = enumerator.Current;
            var key = keySelector(item);

            if (currentKey.Equals(key))
            {
                currentGroup.Add(item);
            }
            else
            {
                yield return currentGroup;
                currentKey = key;
                currentGroup = new List<T> { item };
            }
        }

        // 别忘了返回最后一组
        yield return currentGroup;
    }
}

使用示例

假设你已经有了排序好的List<Order> sortedOrders,直接调用这个扩展方法就行:

// 按连续的DeliveryPerson分组
var consecutiveGroups = sortedOrders.GroupConsecutiveBy(order => order.DeliveryPerson);

// 遍历分组输出结果
foreach (var group in consecutiveGroups)
{
    var firstOrder = group.First();
    var orderIds = string.Join(", ", group.Select(o => $"Order{o.Id}"));
    Console.WriteLine($"Group: {orderIds} [DeliveryPerson: {firstOrder.DeliveryPerson}]");
}

输出结果会和你预期的一致:

Group: Order12 [DeliveryPerson: Andrea]
Group: Order13 [DeliveryPerson: David]
Group: Order14, Order15 [DeliveryPerson: Andrea]
Group: Order16 [DeliveryPerson: Linda]

方法二:手动循环分组(适合快速理解)

如果不想写扩展方法,也可以直接用循环手动构建分组,逻辑更直观,适合新手理解:

List<List<Order>> consecutiveGroups = new List<List<Order>>();

foreach (var order in sortedOrders)
{
    // 如果分组列表为空,或者最后一组的DeliveryPerson和当前订单不同,就新建分组
    if (consecutiveGroups.Count == 0 || consecutiveGroups.Last().First().DeliveryPerson != order.DeliveryPerson)
    {
        consecutiveGroups.Add(new List<Order> { order });
    }
    else
    {
        // 否则加入最后一个分组
        consecutiveGroups.Last().Add(order);
    }
}

关于数据类型的选择

  • 如果只需要遍历处理分组数据,优先用IEnumerable<IEnumerable<Order>>(方法一的返回类型),因为它是懒加载的,内存占用更低,尤其是处理大列表的时候。
  • 如果需要修改分组后的集合(比如添加/删除元素),就用List<List<Order>>(方法二的返回类型),它提供了完整的集合操作方法。

内容的提问来源于stack exchange,提问作者Adrian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 19:47:38