C# Linq跨两个字典聚合数据
我正在与一些linq进行斗争,以实现以下目标:C# Linq跨两个字典聚合数据,c#,linq,C#,Linq,我正在与一些linq进行斗争,以实现以下目标: Dict1 1 0 2 0 3 1 4 1 5 2 6 2 7 2 Dict2 1 45 2 30 3 31 4 43 5 20 6 10 7 5 我想根据dictionary 1中的匹配键对dictionary 2中的值求和,并返回max或任何默认键,结果汇总为0,不包括dict 1中的值 例如: 听起来好像是在按字典1中的值进行
Dict1
1 0
2 0
3 1
4 1
5 2
6 2
7 2
Dict2
1 45
2 30
3 31
4 43
5 20
6 10
7 5
我想根据dictionary 1中的匹配键对dictionary 2中的值求和,并返回max或任何默认键,结果汇总为0,不包括dict 1中的值
例如:
听起来好像是在按字典1中的值进行有效分组。我猜你想要的是: 其结果如下:
4 74
7 35
但它不包括你的{1,45}或{2,30}结果。我认为您希望忽略第一个字典中值为0的条目?因此您希望从第一个字典中获取值不为零的所有对,按字典值对它们进行分组,然后对于每个组,它将表示新字典中的一个条目。该项的键是组中的max键,该值是该键的第二个字典中的值之和 然后用
Concat
将零值添加到末尾,并将其放入字典:
var newDict = dict1.Where(pair => pair.Value != 0)
.GroupBy(pair => pair.Value)
.Select(group => new KeyValuePair<int, int>(
group.Max(pair => pair.Key),
group.Where(pair => dict2.ContainsKey(pair.Key))
.Sum(pair => dict2[pair.Key])))
.Concat(dict1.Where(pair => pair.Value == 0))
.ToDictionary(pair => pair.Key, pair => pair.Value);
var newDict=dict1.Where(pair=>pair.Value!=0)
.GroupBy(pair=>pair.Value)
.选择(组=>new KeyValuePair(
group.Max(pair=>pair.Key),
group.Where(pair=>dict2.ContainsKey(pair.Key))
.Sum(pair=>dict2[pair.Key]))
.Concat(dict1.Where(pair=>pair.Value==0))
.ToDictionary(pair=>pair.Key,pair=>pair.Value);
我想添加此答案作为参考。我不明白为什么其他答案是从dict1开始的?当我们从dict2
这样开始时,会更加方便和容易:
var result = dict2.GroupBy(x => dict1[x.Key] == 0 ? dict1.Min(a=>a.Value) - x.Key :
dict1[x.Key])
.ToDictionary(g => g.Max(x=>x.Key), g => g.Sum(x => x.Value));
或者,如果您不关心1-line LINQ解决方案
,只需声明一些保持dict1
最小值的变量即可(这种方式当然具有更好的性能):
注意:上面的代码可以在某些有限的条件下工作,它不检查
键的存在
,因为它假设两个dict具有相同的键集合(或者至少可以在dict1
中找到dict2
中的所有键。如果dict2
中有一个条目与dict1
中的任何键都不匹配,我们需要更多的规则来处理这种情况,例如在dict2
中保留原始条目。您的要求不清楚。为什么结果中缺少3、5和6s?我想在原始字典中的值不在0的情况下,将这些结果聚合为默认键。因此,firstordefault、max等@PMOrion仍然不清楚,似乎用词来表达并不容易。@PMOrion:啊,我想我明白你的意思,但不是很清楚。如果你排除字典中的值,我会尝试添加一个答案结果如果Dict1值为0,那么为什么结果中的值为1和2。看起来您的结果应该包含键3、4、5、6和7看起来这还需要1个合并步骤来包含值为零的原始条目?@KingKing-Right,谢谢,添加了。1)为什么要获取一个keyvalueapiar,从中获取密钥,然后查找该密钥的值?只需从该对中获取值。您可以在GroupBy
中执行两次此操作。2)为什么要计算min
?如果为0,则程序工作,如果不是,则不工作。只需使用0
而不是min
。3) 这不支持键的负整数,但不确定这是否是真正的问题。4) 你不能处理一个字典有值而另一个没有值的情况。@Servy good point on the 4),对于2)我不同意,如果按0进行分组,我们将只有一组2个条目(1和2),而目的是我们需要两组,一组用于键1,另一组用于键2。嗯,你指出了一些相当大的问题。不过,我认为做一些修改会更好,如果不想说它很快的话,字典中的查找也不是很糟糕。我用OP的样本输入测试了这段代码。计算min
甚至max
的目的是为了找到一种方法,如果(dict1的)条目的值为0
但不需要计算min,就可以得到groupby
的不同值,您可以只使用零,让所有负组键都是零组的键,所有正组键都是非零组的键。如果您这样做的话,您就不能在第二个字典中支持负数键(由于不同的原因,您无论如何也不能支持负数键)。总而言之,你只是想变得太聪明。它使代码更难理解,更难调试,并且在代码中引入了一些小错误。只需添加额外的几行代码,在需求读取时将其写出来即可。基本上,除非有一个int范围没有一个键可以在其中,否则它无法工作。如果您知道没有负数键,那么只需对数字求反,如果您*无法做出该断言,那么您需要进行更根本的更改,以确保在字典值为零的情况下,对象始终是不同的。
var newDict = dict1.Where(pair => pair.Value != 0)
.GroupBy(pair => pair.Value)
.Select(group => new KeyValuePair<int, int>(
group.Max(pair => pair.Key),
group.Where(pair => dict2.ContainsKey(pair.Key))
.Sum(pair => dict2[pair.Key])))
.Concat(dict1.Where(pair => pair.Value == 0))
.ToDictionary(pair => pair.Key, pair => pair.Value);
var result = dict2.GroupBy(x => dict1[x.Key] == 0 ? dict1.Min(a=>a.Value) - x.Key :
dict1[x.Key])
.ToDictionary(g => g.Max(x=>x.Key), g => g.Sum(x => x.Value));
var min = dict1.Min(a=>a.Value);
var result = dict2.GroupBy(x => {
var d = dict1[x.Key];
return d == 0 ? min - Math.Abs(x.Key) : d;
}).ToDictionary(g => g.Max(x=>x.Key), g => g.Sum(x => x.Value));