基于LINQ实现CheckList与dtVoucherEntry匹配TranType、Amount赋值SlNo的问题
匹配凭证条目序号到支票列表的实现优化
现有代码片段
foreach(Cheque details in chklist) { decimal? trantypeValue = dtVoucherEntry .Where(entry => entry.TranType == details.Trantype && entry.Debit == details.Amount) .Select(tran => tran.SlNo) .FirstOrDefault(); if (trantypeValue.HasValue) { details.SlNo = trantypeValue.Value; } }
需求说明
我有一个包含TranType(交易类型)为card及对应Amount(金额)的chklist(支票列表),需要将dtVoucherEntry(凭证条目表)中的SlNo(序号)匹配赋值给chklist的对应项,核心场景分为两类:
chklist与dtVoucherEntry中各有两条TranType为card且金额不同的数据chklist与dtVoucherEntry中各有两条TranType为card且金额相同的数据
示例场景
场景1:金额不同的同类型条目
dtVoucherEntry数据:
- TranType: card,Debit: 50
- TranType: card,Debit: 55
chklist对应包含两条金额分别为50、55的card类型条目,需各自匹配对应SlNo
场景2:金额相同的同类型条目
dtVoucherEntry数据:
- TranType: card,Debit: 50(SlNo: 1)
- TranType: card,Debit: 50(SlNo: 2)
chklist对应包含两条金额为50的card类型条目,需分别匹配到SlNo 1和2,而非都拿到同一个
场景3:混合类型条目
dtVoucherEntry数据:
- TranType: card,Debit: 50
- TranType: tt,Debit: 55
chklist对应包含card类型金额50的条目,仅匹配第一条的SlNo
问题分析
原有代码使用FirstOrDefault()会导致场景2中所有相同金额的chklist条目都拿到dtVoucherEntry中第一条匹配项的SlNo,无法实现一对一的精准匹配。
优化后的实现方案
通过分组+逐个匹配移除已使用的凭证条目,实现精准的一对一赋值:
// 先按TranType和Debit分组,保留每个分组的条目列表 var voucherGroups = dtVoucherEntry .GroupBy(v => new { v.TranType, v.Debit }) .ToDictionary(g => g.Key, g => g.ToList()); foreach (var details in chklist) { var key = new { details.Trantype, details.Amount }; if (voucherGroups.TryGetValue(key, out var matchingVouchers) && matchingVouchers.Any()) { // 取出第一个未匹配的条目 var matchedVoucher = matchingVouchers.First(); details.SlNo = matchedVoucher.SlNo; // 移除已匹配的条目,避免重复匹配 matchingVouchers.Remove(matchedVoucher); } }
方案说明
- 先对
dtVoucherEntry按TranType和Debit分组,将相同类型和金额的条目归类到同一组 - 遍历
chklist时,根据当前条目的类型和金额查找对应分组 - 若分组存在未匹配的条目,取出第一条并赋值SlNo,同时移除该条目,确保后续相同条件的
chklist条目匹配下一个未使用的凭证条目
该方案可完美处理所有场景,包括金额相同的重复条目匹配,保证一对一的精准赋值。
内容的提问来源于stack exchange,提问作者Femeena
相关产品推荐
相关产品推荐

