C# LINQ 查询以查找列表中的项目是否包含在另一个列表中
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12656582/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
LINQ query to find if items in a list are contained in another list
提问by cjohns
I have the following code:
我有以下代码:
List<string> test1 = new List<string> { "@bob.com", "@tom.com" };
List<string> test2 = new List<string> { "[email protected]", "[email protected]" };
I need to remove anyone in test2 that has @bob.com or @tom.com.
我需要删除 test2 中拥有 @bob.com 或 @tom.com 的任何人。
What I have tried is this:
我试过的是这样的:
bool bContained1 = test1.Contains(test2);
bool bContained2 = test2.Contains(test1);
bContained1 = falsebut bContained2 = true. I would prefer not to loop through each list but instead use a Linq query to retrieve the data. bContained1 is the same condition for the Linq query that I have created below:
bContained1 = false但是bContained2 = true。我不想遍历每个列表,而是使用 Linq 查询来检索数据。bContained1 与我在下面创建的 Linq 查询的条件相同:
List<string> test3 = test1.Where(w => !test2.Contains(w)).ToList();
The query above works on an exact match but not partial matches.
上面的查询适用于完全匹配但不适用于部分匹配。
I have looked at other queries but I can find a close comparison to this with Linq. Any ideas or anywhere you can point me to would be a great help.
我查看了其他查询,但我可以找到与 Linq 的密切比较。任何想法或任何您可以指向我的地方都会有很大帮助。
采纳答案by Giscard Biamby
var test2NotInTest1 = test2.Where(t2 => test1.Count(t1 => t2.Contains(t1))==0);
Faster version as per Tim's suggestion:
根据蒂姆的建议更快的版本:
var test2NotInTest1 = test2.Where(t2 => !test1.Any(t1 => t2.Contains(t1)));
回答by walther
No need to use Linq like this here, because there already exists an extension method to do this for you.
这里不需要像这样使用 Linq,因为已经存在一个扩展方法来为您执行此操作。
Enumerable.Except<TSource>
Enumerable.Except<TSource>
http://msdn.microsoft.com/en-us/library/bb336390.aspx
http://msdn.microsoft.com/en-us/library/bb336390.aspx
You just need to create your own comparer to compare as needed.
您只需要创建自己的比较器即可根据需要进行比较。
回答by Trisped
Try the following:
请尝试以下操作:
List<string> test1 = new List<string> { "@bob.com", "@tom.com" };
List<string> test2 = new List<string> { "[email protected]", "[email protected]" };
var output = from goodEmails in test2
where !(from email in test2
from domain in test1
where email.EndsWith(domain)
select email).Contains(goodEmails)
select goodEmails;
This works with the test set provided (and looks correct).
这适用于提供的测试集(并且看起来正确)。
回答by ren
something like this:
像这样:
List<string> test1 = new List<string> { "@bob.com", "@tom.com" };
List<string> test2 = new List<string> { "[email protected]", "[email protected]" };
var res = test2.Where(f => test1.Count(z => f.Contains(z)) == 0)
Live example: here
现场示例:这里
回答by Tim S.
var output = emails.Where(e => domains.All(d => !e.EndsWith(d)));
Or if you prefer:
或者,如果您更喜欢:
var output = emails.Where(e => !domains.Any(d => e.EndsWith(d)));
回答by Francisco Soto
List<string> test1 = new List<string> { "@bob.com", "@tom.com" };
List<string> test2 = new List<string> { "[email protected]", "[email protected]", "[email protected]" };
var result = (from t2 in test2
where test1.Any(t => t2.Contains(t)) == false
select t2);
If query form is what you want to use, this is legible and more or less as "performant" as this could be.
如果查询表单是您想要使用的,那么这是清晰易读的,并且或多或少是“高效的”。
What i mean is that what you are trying to do is an O(N*M) algorithm, that is, you have to traverse N items and compare them against M values. What you want is to traverse the first list only once, and compare against the other list just as many times as needed (worst case is when the email is valid since it has to compare against every black listed domain).
我的意思是你想要做的是一个 O(N*M) 算法,也就是说,你必须遍历 N 个项目并将它们与 M 个值进行比较。您想要的是只遍历第一个列表一次,并根据需要多次与另一个列表进行比较(最坏的情况是电子邮件有效时,因为它必须与每个黑名单域进行比较)。
from t2 in testwe loop the email list once.
from t2 in test我们循环电子邮件列表一次。
test1.Any(t => t2.Contains(t)) == falsewe compare with the blacklist and when we found one match return (hence not comparing against the whole list if is not needed)
test1.Any(t => t2.Contains(t)) == false我们与黑名单进行比较,当我们找到一个匹配项时返回(因此如果不需要,则不与整个列表进行比较)
select t2keep the ones that are clean.
select t2保持那些干净的。
So this is what I would use.
所以这就是我会使用的。
回答by Maruf
I think this would be easiest one:
我认为这将是最简单的一种:
test1.ForEach(str => test2.RemoveAll(x=>x.Contains(str)));
回答by Perry
List<string> l = new List<string> { "@bob.com", "@tom.com" };
List<string> l2 = new List<string> { "[email protected]", "[email protected]" };
List<string> myboblist= (l2.Where (i=>i.Contains("bob")).ToList<string>());
foreach (var bob in myboblist)
Console.WriteLine(bob.ToString());
回答by Rohit Gupta
bool doesL1ContainsL2 = l1.Intersect(l2).Count() == l2.Count;
L1 and L2 are both List<T>
L1 和 L2 都是 List<T>

