我需要在考虑重复项的同时获得两个字符串数组的集合减法。
例如:
var a = new string[] {"1", "2", "2", "3", "4", "4"};
var b = new string[] {"2", "3"};
(a-b)=>预期输出=> string [] {“ 1”,“ 2”,“ 4”,“ 4”}
我已经尝试过Enumerable.Except()
,它在减去后返回 unique 值:{ "1", "4" }
这不是我想要的。
是否有一种无需定制实现的简单方法?
答案 0 :(得分:3)
您可以尝试GroupBy
,并与组一起使用,例如
var a = new string[] {"1", "2", "2", "3", "4", "4"};
var b = new string[] {"2", "3"};
...
var subtract = b
.GroupBy(item => item)
.ToDictionary(chunk => chunk.Key, chunk => chunk.Count());
var result = a
.GroupBy(item => item)
.Select(chunk => new {
value = chunk.Key,
count = chunk.Count() - (subtract.TryGetValue(chunk.Key, out var v) ? v : 0)
})
.Where(item => item.count > 0)
.SelectMany(item => Enumerable.Repeat(item.value, item.count));
// Let's have a look at the result
Console.Write(string.Join(", ", result));
结果:
1, 2, 4, 4
答案 1 :(得分:3)
通过利用下划线的Enumerable.ToLookup
(可让您创建每个键具有多个值的类似字典的结构),您可以非常有效地完成此操作。在这里,由于在ILookup
中不存在的键上进行键查找将返回空的IGrouping
(而不是null
或错误),因此可以避免一堆空检查/ {{ 1}}样板。因为TryGet...
的值等于Enumerable.Take
,所以我们也不必检查算术。
Enumerable.Take(0)
答案 2 :(得分:2)
尝试以下操作:
var a = new string[] { "1", "2", "2", "3", "4", "4" }.ToList();
var b = new string[] { "2", "3" };
foreach (var element in b)
{
a.Remove(element);
}
已经过测试。