LINQ查询以查找列表中的项是否包含在另一个列表中

时间:2012-09-29 21:21:32

标签: c# linq

我有以下代码:

List<string> test1 = new List<string> { "@bob.com", "@tom.com" };
List<string> test2 = new List<string> { "joe@bob.com", "test@sam.com" };

我需要删除test2中有@ bob.com或@ tom.com的人。

我试过的是:

bool bContained1 = test1.Contains(test2);
bool bContained2 = test2.Contains(test1);

bContained1 = falsebContained2 = true。我宁愿不遍历每个列表,而是使用Linq查询来检索数据。 bContained1与我在下面创建的Linq查询的条件相同:

List<string> test3 = test1.Where(w => !test2.Contains(w)).ToList();

上述查询适用于完全匹配,但不适用于部分匹配。

我已经查看了其他查询,但我可以找到与Linq的近似比较。任何想法或任何你可以指向我的地方都会有很大的帮助。

9 个答案:

答案 0 :(得分:60)

var test2NotInTest1 = test2.Where(t2 => test1.Count(t1 => t2.Contains(t1))==0);

根据蒂姆的建议更快的版本:

var test2NotInTest1 = test2.Where(t2 => !test1.Any(t1 => t2.Contains(t1)));

答案 1 :(得分:11)

var output = emails.Where(e => domains.All(d => !e.EndsWith(d)));

或者如果您愿意:

var output = emails.Where(e => !domains.Any(d => e.EndsWith(d)));

答案 2 :(得分:6)

bool doesL1ContainsL2 = l1.Intersect(l2).Count() == l2.Count;

L1和L2都是List<T>

答案 3 :(得分:3)

这里不需要像这样使用Linq,因为已经有一种扩展方法可以帮到你。

Enumerable.Except<TSource>

http://msdn.microsoft.com/en-us/library/bb336390.aspx

您只需要创建自己的比较器,以便根据需要进行比较。

答案 4 :(得分:2)

类似的东西:

List<string> test1 = new List<string> { "@bob.com", "@tom.com" };
List<string> test2 = new List<string> { "joe@bob.com", "test@sam.com" };

var res = test2.Where(f => test1.Count(z => f.Contains(z)) == 0)

实例:here

答案 5 :(得分:0)

尝试以下方法:

List<string> test1 = new List<string> { "@bob.com", "@tom.com" };
List<string> test2 = new List<string> { "joe@bob.com", "test@sam.com" };
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;

这适用于提供的测试集(看起来正确)。

答案 6 :(得分:0)

List<string> test1 = new List<string> { "@bob.com", "@tom.com" };
List<string> test2 = new List<string> { "joe@bob.com", "test@sam.com", "bets@tom.com" };

var result = (from t2 in test2
              where test1.Any(t => t2.Contains(t)) == false
              select t2);

如果你想要使用查询表格,这是可读的,或多或少是“高效”,因为这可能是。

我的意思是你要做的是一个O(N * M)算法,也就是说,你必须遍历N个项目并将它们与M个值进行比较。你想要的只是遍历第一个列表一次,并根据需要多次与其他列表进行比较(最坏的情况是电子邮件有效,因为它必须与每个黑名单域名进行比较)。

from t2 in test我们将电子邮件列表循环一次。

test1.Any(t => t2.Contains(t)) == false我们与黑名单进行比较,当我们找到一个匹配返回时(因此如果不需要则不与整个列表进行比较)

select t2保留那些干净的。

所以这就是我要用的。

答案 7 :(得分:-3)

List<string> l = new List<string> { "@bob.com", "@tom.com" };
List<string> l2 = new List<string> { "joe@bob.com", "test@bob.com" };
List<string> myboblist= (l2.Where (i=>i.Contains("bob")).ToList<string>());
foreach (var bob in myboblist)
    Console.WriteLine(bob.ToString());

答案 8 :(得分:-4)

我认为这是最简单的一个:

test1.ForEach(str => test2.RemoveAll(x=>x.Contains(str)));