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

如何使用Linq对列表中连续相同值的项进行分组

用LINQ实现连续相同Name项的分组筛选

先看你给出的原始数据:

var schedules = new List<Item>{ 
    new Item { Id=1, Name = "S" }, 
    new Item { Id=2, Name = "P" }, 
    new Item { Id=3, Name = "X" }, 
    new Item { Id=4, Name = "X" }, 
    new Item { Id=5, Name = "P" }, 
    new Item { Id=6, Name = "P" }, 
    new Item { Id=7, Name = "P" }, 
    new Item { Id=8, Name = "S" } 
};

你的需求很明确:要把连续相同Name的项归为子列表,而且只保留元素数量≥2的组,最终结果应该是这样:

var groupedAndSelectedList = new List<List<Item>>{ 
    new List<Item> { new Item { Id=3, Name = "X" }, new Item { Id=4, Name = "X" } }, 
    new List<Item> { new Item { Id=5, Name = "P" }, new Item { Id=6, Name = "P" }, new Item { Id=7, Name = "P" } } 
};

确实,普通的GroupBy会把所有同名的项都塞到一组里,不管是不是连续的,所以得换个思路用LINQ实现。这里给你两种可行的方案:

方案一:用Aggregate跟踪分组状态

Aggregate方法可以帮我们在遍历过程中跟踪当前的分组状态,非常适合这种连续分组的场景:

var result = schedules.Aggregate(new List<List<Item>>(), (groups, currentItem) =>
{
    // 检查有没有分组,或者最后一组的Name和当前元素不一致
    if (!groups.Any() || groups.Last().First().Name != currentItem.Name)
    {
        // 新建一个分组,把当前元素加进去
        groups.Add(new List<Item> { currentItem });
    }
    else
    {
        // 把当前元素加入最后一个同名单分组
        groups.Last().Add(currentItem);
    }
    return groups;
})
// 过滤掉只有单个元素的分组
.Where(group => group.Count >= 2)
.ToList();

逻辑说明:

  1. 初始化一个空的分组列表作为累积器;
  2. 逐个遍历原始列表的元素:
    • 如果还没有分组,或者最后一个分组的Name和当前元素不同,就新建一个分组;
    • 如果Name相同,就把当前元素追加到最后一个分组里;
  3. 最后过滤掉元素数小于2的分组,得到符合要求的结果。

方案二:给连续组分配唯一ID再分组

这种方式更直观,先给每个连续的同名序列分配一个递增的GroupId,再按ID分组:

int currentGroupId = 0;
string previousName = null;

var result = schedules
    .Select(item => 
    {
        // 如果当前元素Name和上一个不同,就更新分组ID
        if (item.Name != previousName)
        {
            currentGroupId++;
            previousName = item.Name;
        }
        return new { Item = item, GroupId = currentGroupId };
    })
    .GroupBy(groupedItem => groupedItem.GroupId)
    .Select(group => group.Select(g => g.Item).ToList())
    .Where(group => group.Count >= 2)
    .ToList();

逻辑说明:

  1. 用两个变量跟踪当前分组ID和上一个元素的Name;
  2. 遍历每个元素时,判断Name是否变化,变化就递增分组ID;
  3. 按分组ID进行GroupBy,再把每个组转成Item列表;
  4. 最后过滤掉小分组即可。

两种方案都能完美实现你的需求,选哪种看你个人习惯~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:26:37