c# - 在一个键上加入两个列表,并用 CROSS 总结总数?
问题描述
我有两个List<AccountBalance>
AccountBalance 有一个 IDGUID
和一个 BalanceDECIMAL
值。
一份清单包含所有贷方,一份清单包含所有借方。这些已经相加,因此列表中会有唯一的帐户 ID(但会在另一个中重复。即,一个帐户将在 creditBalances 中出现一次,但可能会在两个列表中找到。
var creditBalances = new List<AccountBalance>();
var debiBalances = new List<AccountBalance>();
我需要做的是返回一个列表,其中包含每个帐户的总数。
所以,我需要根据两个表的 ID 进行连接……对于每个帐户,在贷方中添加金额,并在借方中减去金额。
并非所有账户都有贷方,也不是所有账户都有借方,但我的结果集需要包含所有账户。
我正在尝试什么:
var result = creditBalances
.Join(debitBalances, a => a.ExternalId, b => b.ExternalId, (a, b) => new AccountBalance { Id = a.ExternalId, Balance = a.amount - b.amount })
.ToList();
但这似乎是一个内部连接,并且只给我“creditBalances”有价值的结果。我基本上需要做一个交叉连接?
信用:
Acc: 1, amount 10
Acc: 2, amount 5
借方:
Acc 2: amount 2
Acc 3: amount 5
应该导致:
Acc 1: 10
Acc 2: 3
Acc 3: -5
解决方案
你可以做一个完整的外部连接。
适应您的具体情况:
public class AccountBalance
{
public decimal amount { get; set; }
public decimal ExternalId { get; set; }
}
// From https://stackoverflow.com/a/13503860/11981207
public static IEnumerable<TResult> FullOuterJoin<TA, TB, TKey, TResult>(
this IEnumerable<TA> a,
IEnumerable<TB> b,
Func<TA, TKey> selectKeyA,
Func<TB, TKey> selectKeyB,
Func<TA, TB, TKey, TResult> projection,
TA defaultA = default(TA),
TB defaultB = default(TB),
IEqualityComparer<TKey> cmp = null)
{
cmp = cmp ?? EqualityComparer<TKey>.Default;
var alookup = a.ToLookup(selectKeyA, cmp);
var blookup = b.ToLookup(selectKeyB, cmp);
var keys = new HashSet<TKey>(alookup.Select(p => p.Key), cmp);
keys.UnionWith(blookup.Select(p => p.Key));
var join = from key in keys
from xa in alookup[key].DefaultIfEmpty(defaultA)
from xb in blookup[key].DefaultIfEmpty(defaultB)
select projection(xa, xb, key);
return join;
}
// ---
var creditBalances = new List<AccountBalance> {
new AccountBalance { ExternalId = 1, amount = 10 },
new AccountBalance { ExternalId = 2, amount = 5 },
};
var debitBalances = new List<AccountBalance> {
new AccountBalance {ExternalId = 2, amount = 2 },
new AccountBalance { ExternalId = 3, amount = 5 },
};
var result = creditBalances.FullOuterJoin(debitBalances,
credit => credit.ExternalId,
debit => debit.ExternalId,
(credit, debit, key) =>
new AccountBalance() {
ExternalId = key,
amount= (credit?.amount ?? 0) - (debit?.amount ?? 0)
}
);
推荐阅读
- c# - 如何在restsharp中编写这个cURL?
- .net - linux中dumpheap sos插件中的未知类
- react-native - 如何在 react-native-video 中隐藏声音和全屏按钮
- docker - Cloudant docker 映像太旧,无法使用“分区”选项
- sql-server - SQL 查询使站点崩溃或没有从 SQL 响应以执行查询
- email - Sendy - OroCRM 是否可以使用 Sendy 扩展程序?
- python - 按一列中的值对我的数据框进行分组?
- r - 如何使用带有“出生日期”列的 age_calc 函数?
- laravel - 上传文件,文件路径为空,VueJs / Laravel
- c# - 如何在使用 Blazor 的 ASP.NET CORE 中更新数据库后刷新网页