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

C#中按属性连续分组对象并处理例外情况的问题

问题:按Theme连续分组并排除指定Alias项的分组逻辑修正

原始数据定义

public class BlockListItem
{
    public int Id { get; set; }
    public string Alias { get; set; }
    public string Theme { get; set; }
}

IEnumerable<BlockListItem> items = new List<BlockListItem>
{
    new() { Id = 1, Alias = "A", Theme = "Red" },
    new() { Id = 2, Alias = "A", Theme = "Red" },
    new() { Id = 3, Alias = "B", Theme = "Red" },
    new() { Id = 4, Alias = "C", Theme = "Red" },
    new() { Id = 5, Alias = "C", Theme = "Red" },
    new() { Id = 6, Alias = "A", Theme = "Red" },
    new() { Id = 7, Alias = "A", Theme = "Blue" },
};

分组规则与预期结果

指定不可分组的Alias数组:

var ungroupableAliases = new[] { "C" };

分组规则:

  • 连续且Theme相同、且Alias不在不可分组列表中的项归为一组
  • 不可分组的项(Alias为C)单独成组
  • 前一项是不可分组项时,后续项即使Theme相同也必须单独成组
  • Theme不同的项单独成组

预期分组结果:

--------------------------------------
{ Id = 1, Alias = "A", Theme = "Red" }
{ Id = 2, Alias = "A", Theme = "Red" }
{ Id = 3, Alias = "B", Theme = "Red" }
--------------------------------------
{ Id = 4, Alias = "C", Theme = "Red" }
--------------------------------------
{ Id = 5, Alias = "C", Theme = "Red" }
--------------------------------------
{ Id = 6, Alias = "A", Theme = "Red" }
--------------------------------------
{ Id = 7, Alias = "A", Theme = "Blue" }

现有代码问题

现有实现方法会错误地将项6与项5归为一组,不符合预期:

private static List<List<BlockListItem>> GroupItems(IEnumerable<BlockListItem> items, string[] ungroupableAliases)
{
    if (items == null || !items.Any())
    {
        return new List<List<BlockListItem>>();
    }

    var itemGroups = new List<List<BlockListItem>>();
    var currentItemGroup = new List<BlockListItem> { items.First() };

    foreach (var item in items.Skip(1))
    {
        var itemIsGroupable = item.Theme == currentItemGroup.First().Theme && !ungroupableAliases.Contains(item.Alias);

        if (!itemIsGroupable)
        {
            itemGroups.Add(currentItemGroup.ToList());
            currentItemGroup = new List<BlockListItem>(); // Create a new group for ungroupable items.
        }

        currentItemGroup.Add(item);
    }

    itemGroups.Add(currentItemGroup.ToList());

    return itemGroups;
}

问题根源:仅判断当前项是否符合分组条件,未考虑当前组的最后一项是否为不可分组项——如果前一项是不可分组的,后续项必须单独成组,不能加入当前组。

修正后的实现

private static List<List<BlockListItem>> GroupItems(IEnumerable<BlockListItem> items, string[] ungroupableAliases)
{
    if (items == null || !items.Any())
    {
        return new List<List<BlockListItem>>();
    }

    var itemGroups = new List<List<BlockListItem>>();
    var currentItemGroup = new List<BlockListItem> { items.First() };

    foreach (var item in items.Skip(1))
    {
        var lastItemInCurrentGroup = currentItemGroup.Last();
        // 判断当前项能否加入当前组的条件:
        // 1. 当前组的最后一项不是不可分组项
        // 2. 当前项的Theme与当前组的Theme一致
        // 3. 当前项本身是可分组的(不在不可分组列表中)
        var canAddToCurrentGroup = !ungroupableAliases.Contains(lastItemInCurrentGroup.Alias)
                                   && item.Theme == currentItemGroup.First().Theme
                                   && !ungroupableAliases.Contains(item.Alias);

        if (!canAddToCurrentGroup)
        {
            // 无法加入当前组,先保存当前组
            itemGroups.Add(currentItemGroup.ToList());
            // 创建新组放入当前项
            currentItemGroup = new List<BlockListItem> { item };
        }
        else
        {
            // 可以加入,直接添加到当前组
            currentItemGroup.Add(item);
        }
    }

    // 处理最后一组
    itemGroups.Add(currentItemGroup.ToList());

    return itemGroups;
}

关键改动说明

  1. 增加前一项的判断:检查当前组最后一项是否为不可分组项,如果是,当前项必须单独成组
  2. 调整分组条件逻辑:只有当前组可继续扩展(最后一项不是不可分组)、当前项Theme匹配、当前项可分组这三个条件同时满足时,才将当前项加入当前组
  3. 修正新组创建逻辑:无法加入当前组时,直接创建新组并放入当前项,避免之前的“先清空再添加”导致的错误合并

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 21:09:53