LINQ获取两个列表的差异->;保留副本

LINQ获取两个列表的差异->;保留副本,linq,Linq,假设两个列表A和B Dim A as New List(Of String) ( {"011", "011", "012", "001"}) Dim B as New List(Of String) ( {"011", "012", "111"}); 我想得到从A到B的差异,在这个例子中:[“011”,“001”] 列表A和B都可能包含重复的条目。如果列表A包含一个重复的元素e,而列表B只有一次相同的值e//小于A,则结果列表应包含(A中的次数e)-(B中的次数e)e 例如: ["001",

假设两个列表A和B

Dim A as New List(Of String) ( {"011", "011", "012", "001"})
Dim B as New List(Of String) ( {"011", "012", "111"});
我想得到从A到B的差异,在这个例子中:
[“011”,“001”]

列表A和B都可能包含重复的条目。如果列表A包含一个重复的元素e,而列表B只有一次相同的值e//小于A,则结果列表应包含
(A中的次数e)-(B中的次数e)
e

例如:

["001", "001", "001", "002"] ~ ["001", "001", "003" ] -> ["001", "002"]
这个问题的解决方案在经典的编程方式中是微不足道的,但我希望使用LINQ获得一个(较短的)解决方案,但到目前为止,我找不到一段工作代码,因为
相交,除了和并集
都切掉了我需要保留的重复项


我很高兴看到一个简单的LINQ解决方案

一个干净地使用
ToLookup
的替代方案可能是值得的——特别是如果列表变得很大的话

var tmp = b.ToList();
var result = a.Where(s => !tmp.Remove(s)).ToList();
这是:

Dim AL = A.ToLookup(Function (x) x)
Dim BL = B.ToLookup(Function (x) x)

Dim C = _
    AL _
        .SelectMany(Function (xs) xs.Skip(BL(xs.Key).Count())) _
        .ToList()
或者,在c#中:


您需要
吗!tmp.包含| |
?我想你可以不用它。我喜欢这样,它保持了
a
的顺序,就像
一样,除了
等等。也许你可以通过制作
tmp
一本字典或其他东西来加快它的速度,但是对于一个两行程序来说,这很好。这正是我想要的!非常感谢@鲍里斯。解决方案无法使用哈希集![“a”、“a”、“a”]~[“a”、“a”]->[“a”]但是使用哈希集,您会得到->[“a”、“a”]结果(这是错误的!)@juq:Yep,两个具有相同内容的字符串具有相同的标识,将把答案还原为list。这是一个很好的实现,但我的两个列表都包含0-10(最多!)个元素,通常是2-4,因此,我认为创建查找所产生的开销对于我想要实现的目标来说太大了!谢谢你的主意,regards@juq-由于列表太小而导致的开销?代码运行在先进的现代硬件上,对吗?只有当你的清单很大的时候,你才应该担心。您应该担心的是可维护性。然后你想得到最简单的代码。
var AL = A.ToLookup(x => x);
var BL = B.ToLookup(x => x);

var C =
    AL
        .SelectMany(xs => xs.Skip(BL[xs.Key].Count()))
        .ToList();