我想要交叉两个集合,并对匹配元素执行求和操作。
例如,集合是(伪代码):
col1 = { {"A", 5}, {"B", 3}, {"C", 2} }
col2 = { {"B", 1}, {"C", 8}, {"D", 6} }
,所需的结果是:
intersection = { {"B", 4}, {"C", 10} }
我知道如何使用IEqualityComparer
来匹配其名称上的元素,但是如何在进行交集时对值进行求和?
编辑:
起始集合中没有两个具有相同名称的项目。
答案 0 :(得分:1)
假设您的输入数据如下所示:
IEnumerable<Tuple<string, int>> firstSequence = ..., secondSequence = ...;
如果每个序列中的字符串都是唯一的(即任一序列中只能有一个{“A”,XXX}),您可以join
这样:
var query = from tuple1 in firstSequence
join tuple2 in secondSequence on tuple1.Item1 equals tuple2.Item1
select Tuple.Create(tuple1.Item1, tuple1.Item2 + tuple2.Item2);
您可能还想考虑使用group by
,如果此唯一性不成立则更合适:
var query = from tuple in firstSequence.Concat(secondSequence)
group tuple.Item2 by tuple.Item1 into g
select Tuple.Create(g.Key, g.Sum());
如果两者都不合适,请更准确地澄清您的要求。
编辑:在您澄清这些是字典后 - 您现有的解决方案完全没问题。这是join
的另一种选择:
var joined = from kvp1 in dict1
join kvp2 in dict2 on kvp1.Key equals kvp2.Key
select new { kvp1.Key, Value = kvp1.Value + kvp2.Value };
var result = joined.ToDictionary(t => t.Key, t => t.Value);
或流利的语法:
var result = dict1.Join(dict2,
kvp => kvp.Key,
kvp => kvp.Key,
(kvp1, kvp2) => new { kvp1.Key, Value = kvp1.Value + kvp2.Value })
.ToDictionary(a => a.Key, a => a.Value);
答案 1 :(得分:1)
这将给出结果,但有一些警告。它组合了两个集合,然后按字母对它们进行分组。例如,如果col1
包含两个A
元素,它会将它们相加在一起,因为现在它们是2 A
,它会返回它们。
var col1 = new[] { new { L = "A", N = 5 }, new { L = "B", N = 3 }, new { L = "C", N = 2 } };
var col2 = new[] { new { L = "B", N = 1 }, new { L = "C", N = 8 }, new { L = "D", N = 6 } };
var res = col1.Concat(col2)
.GroupBy(p => p.L)
.Where(p => p.Count() > 1)
.Select(p => new { L = p.Key, N = p.Sum(q => q.N) })
.ToArray();
答案 2 :(得分:1)
我想到的最好的是(我的馆藏实际上是Dictionary<string, int>
个实例):
var intersectingKeys = col1.Keys.Intersect(col2.Keys);
var intersection = intersectingKeys
.ToDictionary(key => key, key => col1[key] + col2[key]);
我不确定它是否会表现良好,至少是否可读。
答案 3 :(得分:0)
如果您的交集算法会产生匿名类型,即...Select(new { Key = key, Value = value})
,那么您可以很容易地将其加总
result.Sum(e => e.Value);
如果要对执行交集的“while”求和,请在添加到结果集时将值添加到累加器值。