检查list <t>是否包含另一个列表


97

我有这样的参数列表:

public class parameter
{
    public string name {get; set;}
    public string paramtype {get; set;}
    public string source {get; set;}
}

IEnumerable<Parameter> parameters;

和我想检查的字符串数组。

string[] myStrings = new string[] { "one", "two"};

我想遍历参数列表,并检查source属性是否等于任何myStrings数组。我可以使用嵌套的foreach来做到这一点,但是我想以更好的方式学习如何做,因为我一直在使用linq并喜欢枚举的扩展方法,例如where等,所以嵌套的foreach感觉不对。有没有更优雅的首选linq / lambda / delegete方法来做到这一点。

谢谢

Answers:


207

您可以使用嵌套Any()的此检查,该检查适用于任何Enumerable

bool hasMatch = myStrings.Any(x => parameters.Any(y => y.source == x));

在较大的集合上执行得更快的方法是先投影parameterssource然后使用Intersect它,在内部使用HashSet<T>so而不是O(n ^ 2)作为第一种方法(相当于两个嵌套循环),您可以在O(n)中进行检查:

bool hasMatch = parameters.Select(x => x.source)
                          .Intersect(myStrings)
                          .Any(); 

另外,作为旁注,您应该大写您的类名和属性名,以符合C#样式准则。


感谢似乎是什么即时通讯寻找我会尝试一下。需要更多地处理功能方面的问题。关于大写的类和属性,我做上面的示例时只是忘了。
gdp 2012年

1
为什么是O(n ^ 2)?当我们在谈论两个变量而不是一个时,它不是O(n * m)吗?由于m(参数)是一个常数,因此它与O(n)相同。我看不到这里的相交应该更快吗?但是同意,相交有潜力更快,但并不能保证。
Squazz

没错,它应该是O(n * m)-尽管m不是常数-它是列表之一的大小,即使在给出的特定示例中它可能是“ 2”。即使常数值在实践中也可以忽略不计-对于所有非平凡的列表长度,Intersect速度会更快-如果列表非常短,则无论哪种方式都无关紧要(在这种情况下,性能可能根本不是您关心的问题) )
BrokenGlass '16

您如何找出条件变为真的列表索引?我有一个句子清单。我有一个包含特定单词的数组。如果句子中的数组中至少有一个单词,我需要列表的索引。@BrokenGlass
kirushan

1
在性能方面,会parameters.Any(x => myStrings.Contains(x.source));比您的第一个示例更好吗?
Fluppe

3

这是一个示例,用于查找另一个列表中是否有匹配元素

List<int> nums1 = new List<int> { 2, 4, 6, 8, 10 };
List<int> nums2 = new List<int> { 1, 3, 6, 9, 12};

if (nums1.Any(x => nums2.Any(y => y == x)))
{
    Console.WriteLine("There are equal elements");
}
else
{
    Console.WriteLine("No Match Found!");
}

2
请注意,如果涉及的列表很大,则最终会比Intersect方法慢很多,因为列表大小为O(N * M)。(虽然它在内存中是O(1)。)
乔恩·斯凯特

1

如果两个列表都太大,并且当我们使用lamda表达式时,提取将花费很长时间。在这种情况下最好使用linq来获取参数列表:

var items = (from x in parameters
                join y in myStrings on x.Source equals y
                select x)
            .ToList();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.