I want to know if at least one element in a first list can be found in a second list.
I can see two ways to do it. Let's say our lists are:
List<string> list1 = new[] { "A", "C", "F", "H", "I" };
List<string> list2 = new[] { "B", "D", "F", "G", "I" };
The first approach uses a loop:
bool isFound = false;
foreach (item1 in list1)
{
if (list2.Contains(item1))
{
isFound = true;
break;
}
}
The second one uses Linq directly:
bool isFound = list1.Intersect(li开发者_开发知识库st2).Any();
The first one is long to write and not very straightforward/easy-to-read. The second one is short and clear, but performances will be low, especially on large lists.
What may be an elegant way to do it?
The second one has better performance on large lists than the first one. Intersect
puts the elements of one list into a hash table before checking the other list's elements for membership.
It seems odd to critique the performance of LINQ when the original is clearly (worst case) O(n*m); the LINQ approach would I expect use a HashSet<T>
on a list, and then use a streaming iterator block - so the performance should be O(n+m) - i.e. better.
I think the second one will be faster for large lists. Since the first one is O(list1.Count*list2.Count) whereas the second is O(list1.Count+list2.Count). Second one takes more memory though.
And the overhead of linq is typically a constant multiplication factor over handcrafted code. I'd guess the second one is slower than imperative code by at most a factor of two, probably not even that. It uses O(list1.Count+list2.Count)
memory which can be cut down to O(Min(list1,list2))
if you carefully write your code for low memory usage whilte retaining linear performance.
This code should be relatively fast on large lists:
bool isFound = false;
HashSet<string> set2=new HashSet<string>(list2);
foreach (item1 in list1)
{
if (set2.Contains(item1))
{
isFound = true;
break;
}
}
You can optimize this code further by making the smaller list into a hashset instead of always using list2.
The accepted answer is great, however it does not work with Linq-to-sql, since there's no mapping for Intersect
.
In that case you should use :
bool isFound = table.Any(row => list2.Contains(row.FieldWithValue));
This gets compiled to WHERE EXSITS
This is another way to know if an element of one list exists in another list.
bool present = List1.Any(t => List2.Any(y => y == t));
精彩评论