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; }
关键改动说明
- 增加前一项的判断:检查当前组最后一项是否为不可分组项,如果是,当前项必须单独成组
- 调整分组条件逻辑:只有当前组可继续扩展(最后一项不是不可分组)、当前项Theme匹配、当前项可分组这三个条件同时满足时,才将当前项加入当前组
- 修正新组创建逻辑:无法加入当前组时,直接创建新组并放入当前项,避免之前的“先清空再添加”导致的错误合并
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

