按优先级对IEnumerable<TransactionLineDto>进行分区的技术实现问询
嘿,这个需求我刚好有过类似的实现经验,咱们来一步步搞定它~
实现方案:按折扣作用规则分区交易行
先明确需求核心
接收
IEnumerable<TransactionLineDto>集合,其中包含商品(Article)和折扣(Discount);折扣仅作用于其之前的商品,直到遇到下一个折扣;集合可无折扣,也可包含多个折扣,但单个商品不可被多个折扣覆盖,最终要按规则分区。
核心思路
本质上就是把「折扣」作为分组分隔点,把它前面的所有未绑定折扣的商品打包成一组,和这个折扣绑定。具体逻辑很直观:
- 遍历集合时,维护一个临时列表存放当前未被折扣绑定的商品
- 遇到商品:直接加入临时列表
- 遇到折扣:把临时列表里的所有商品和这个折扣组成一个分区,然后清空临时列表,准备接收下一组商品
- 遍历结束后,如果临时列表还有剩余商品(没有后续折扣),单独作为一个无折扣的分区
代码实现
首先假设TransactionLineDto有标识类型的属性(比如枚举或布尔值),先定义基础类型:
// 定义交易行类型枚举 public enum TransactionLineType { Article, Discount } public class TransactionLineDto { public TransactionLineType Type { get; set; } public string Name { get; set; } // 示例属性,实际根据业务调整 // 其他业务属性:比如金额、ID、商品编码等 }
然后写一个扩展方法来实现分区逻辑,这样调用起来更优雅:
public static class TransactionExtensions { public static IEnumerable<(IEnumerable<TransactionLineDto> Articles, TransactionLineDto? Discount)> PartitionByDiscountScope(this IEnumerable<TransactionLineDto> lines) { var currentArticles = new List<TransactionLineDto>(); foreach (var line in lines) { switch (line.Type) { case TransactionLineType.Article: currentArticles.Add(line); break; case TransactionLineType.Discount: // 只有当有商品时才生成分区,避免无商品的无效折扣 if (currentArticles.Any()) { yield return (currentArticles.AsEnumerable(), line); currentArticles.Clear(); } break; } } // 处理最后一组没有折扣的剩余商品 if (currentArticles.Any()) { yield return (currentArticles.AsEnumerable(), null); } } }
示例验证
比如你的示例输入:Article1 -> Article2 -> Discount1 -> Article3 -> Discount2 -> Article4
调用方法后会得到3个分区:
- 第一组:
Articles = [Article1, Article2], Discount = Discount1 - 第二组:
Articles = [Article3], Discount = Discount2 - 第三组:
Articles = [Article4], Discount = null
边界情况处理
- 只有商品无折扣:返回一个分区,
Discount为null - 开头就是折扣:这个折扣没有对应的商品,会被忽略(完全符合“折扣作用于之前商品”的规则)
- 连续多个折扣:第一个折扣会绑定前面的商品(如果有的话),后续的折扣因为前面没有商品,会被自动跳过
- 大集合场景:用
yield return实现延迟执行,不会一次性加载所有数据到内存,性能友好
内容的提问来源于stack exchange,提问作者Spotted
相关产品推荐
相关产品推荐

