C#按Alias属性连续分组对象,保留顺序并处理不可分组项
按连续Alias分组并处理不可分组项的简洁实现方案
这里给你一个简洁的扩展方法实现,完全满足按连续Alias分组、不可分组项单独成组且严格保留原顺序的需求:
public static IEnumerable<List<BlockListItem>> GroupByContinuousAlias(this IEnumerable<BlockListItem> items, HashSet<string> ungroupableAliases) { if (items == null) throw new ArgumentNullException(nameof(items)); if (ungroupableAliases == null) throw new ArgumentNullException(nameof(ungroupableAliases)); List<BlockListItem> currentGroup = null; foreach (var item in items) { // 不可分组的项,单独成组 if (ungroupableAliases.Contains(item.Alias)) { // 先输出之前未完成的组(如果有) if (currentGroup != null) { yield return currentGroup; currentGroup = null; } // 当前项单独作为一组输出 yield return new List<BlockListItem> { item }; continue; } // 可分组的项,判断是否能加入当前组 if (currentGroup == null) { currentGroup = new List<BlockListItem> { item }; } else if (currentGroup[0].Alias == item.Alias) { currentGroup.Add(item); } else { // 当前组Alias与当前项不同,输出当前组并新建组 yield return currentGroup; currentGroup = new List<BlockListItem> { item }; } } // 遍历结束后,输出最后一个未处理的组 if (currentGroup != null) { yield return currentGroup; } }
逻辑说明
- 用
currentGroup变量维护正在构建的当前分组,全程遍历一次集合,性能高效 - 遇到不可分组Alias时,先输出之前的分组(如果存在),再将当前项单独作为一组输出
- 可分组项会检查是否与当前组的Alias一致,一致则加入,不一致则输出当前组并新建分组
- 使用
HashSet<string>存储不可分组Alias是为了获取O(1)的查询效率,比List.Contains的O(n)更高效
使用示例
// 定义BlockListItem类 public class BlockListItem { public string Alias { get; set; } public string Name { get; set; } } // 测试数据 var items = new List<BlockListItem> { new BlockListItem { Alias = "A", Name = "Item 1" }, new BlockListItem { Alias = "A", Name = "Item 2" }, new BlockListItem { Alias = "B", Name = "Item 3" }, new BlockListItem { Alias = "C", Name = "Item 4" }, new BlockListItem { Alias = "C", Name = "Item 5" }, new BlockListItem { Alias = "A", Name = "Item 6" }, new BlockListItem { Alias = "A", Name = "Item 7" } }; // 不可分组Alias集合 var ungroupableAliases = new HashSet<string> { "C" }; // 执行分组 var groups = items.GroupByContinuousAlias(ungroupableAliases); // 输出分组结果 int groupCount = 1; foreach (var group in groups) { Console.WriteLine($"Group {groupCount}"); foreach (var item in group) { Console.WriteLine($" {item.Name} (alias {item.Alias})"); } groupCount++; }
运行后会输出你期望的分组结果,且完全保留原集合的顺序。
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

