如何将对象列表项插入指定分组末尾并保留原有排序
问题描述
有两个Author对象列表authors1和authors2,其中authors1已按SDate字段排序。需求是将authors2中的项添加到authors1中,保持原有排序的同时,所有新增项需放在对应Book分组的末尾。
现有代码
IList<Author> authors1 = new List<Author> { new Author { Book = "c#", Code="A11" , SDate = 1 }, new Author { Book = "c#", Code="A22" , SDate = 1 }, new Author { Book = "c#", Code="A31" , SDate = 1 }, new Author { Book = "js", Code="B43" , SDate = 2 }, new Author { Book = "js", Code="B33" , SDate = 2 }, new Author { Book = "js", Code="B41" , SDate = 2 }, new Author { Book = "java", Code="C27", SDate = 3 }, new Author { Book = "java", Code="C33", SDate = 3 }, new Author { Book = "java", Code="C78", SDate = 3 } }; IList<Author> authors2 = new List<Author> { new Author { Book = "c#", Code = "A21" }, new Author { Book = "java", Code = "C23" } };
预期结果
IList<Author> authors1 = new List<Author> { new Author { Book = "c#", Code="A11", SDate = 1 }, new Author { Book = "c#", Code="A22", SDate = 1 }, new Author { Book = "c#", Code="A31", SDate = 1 }, new Author { Book = "c#", Code="A21", SDate = 1 }, // 新增项添加到该分组末尾 new Author { Book = "js", Code="B43", SDate = 2 }, new Author { Book = "js", Code="B33", SDate = 2 }, new Author { Book = "js", Code="B41", SDate = 2 }, new Author { Book="java", Code="C27", SDate=3 }, new Author { Book="java", Code="C33", SDate=3 }, new Author { Book="java", Code="C78", SDate=3 }, new Author { Book="java", Code="C23", SDate=3 } // 新增项添加到该分组末尾 };
当前尝试的代码片段
IList<Author> response = new List<Author>(); foreach (var author in authors2.GroupBy(x => x.Book).ToList()) { foreach (var item in author) {
解决方案
方法一:分组拼接法
先将authors1按Book分组,把authors2的项补充到对应分组(同步设置SDate),最后按原SDate顺序拼接所有分组,高效实现需求:
// 把authors1按Book分组,保存每个分组的SDate和作者列表 var groupedAuthors1 = authors1.GroupBy(a => a.Book) .ToDictionary(g => g.Key, g => new { SDate = g.First().SDate, Authors = g.ToList() }); // 处理authors2中的每个项,补充到对应分组 foreach (var author in authors2) { if (groupedAuthors1.TryGetValue(author.Book, out var groupInfo)) { // 设置和同分组一致的SDate author.SDate = groupInfo.SDate; groupInfo.Authors.Add(author); } else { // 处理authors1中没有的Book分组(可选逻辑,这里设置SDate为现有最大值+1) var maxSDate = groupedAuthors1.Values.Max(v => v.SDate); author.SDate = maxSDate + 1; groupedAuthors1.Add(author.Book, new { SDate = author.SDate, Authors = new List<Author> { author } }); } } // 按原SDate顺序排序分组,拼接成最终列表 var result = groupedAuthors1.Values.OrderBy(v => v.SDate) .SelectMany(v => v.Authors) .ToList();
方法二:遍历插入法
遍历authors1的同时跟踪当前Book分组,在分组切换时插入对应authors2的项,严格保持原分组内的顺序:
IList<Author> response = new List<Author>(); // 把authors2按Book分组,方便快速查找 var authors2Grouped = authors2.GroupBy(a => a.Book) .ToDictionary(g => g.Key, g => g.ToList()); string currentBook = null; foreach (var author in authors1) { if (currentBook != author.Book) { // 切换分组时,先把上一个分组的新增项加入列表(第一次循环跳过) if (currentBook != null && authors2Grouped.TryGetValue(currentBook, out var itemsToAdd)) { var sDate = authors1.First(a => a.Book == currentBook).SDate; foreach (var item in itemsToAdd) { item.SDate = sDate; response.Add(item); } } currentBook = author.Book; } response.Add(author); } // 处理最后一个分组的新增项 if (currentBook != null && authors2Grouped.TryGetValue(currentBook, out var lastItemsToAdd)) { var sDate = authors1.First(a => a.Book == currentBook).SDate; foreach (var item in lastItemsToAdd) { item.SDate = sDate; response.Add(item); } }
两种方法都能满足需求:保持authors1原有排序,新增项放在对应Book分组的末尾,同时自动同步SDate字段。
内容的提问来源于stack exchange,提问作者suc pepe
相关产品推荐
相关产品推荐

