So I wrote this simple console app to aid in my question asking. What is the proper way to use a lambda expression on line 3 of the method to get the common members. Tried a Join() but couldn't figure out the correct syntax. As follow up... is there a non-LINQ way to do this in one line that I missed?
class Program
{
static void Main(string[] args)
{
List<int> c = new List<int>() { 1, 2, 3 };
List<int> a = new List<int>() { 5, 3, 2, 4 };
IEnumerable<int> j = c.Union<int>(a);
// just show me the Count
Console.Write(j.ToList<int>().Count.ToString());
}
}
You want Intersect()
:
IEnumerable<int> j = c.Intersect(a);
Here's an OrderedIntersect()
example based on the ideas mentioned in the comments. If you know your sequences are ordered it should run faster — O(n)
rather than whatever .Intersect()
normally is (don't remember off the top of my head). But if you don't know they are ordered, it likely won't return correct results at all:
public static IEnumerable<T> OrderedIntersect<T>(this IEnumerable<T> source, IEnumerable<T> other) where T : IComparable
{
using (var xe = source.GetEnumerator())
using (var ye = other.GetEnumerator())
{
while (xe.MoveNext())
{
while (ye.MoveNext() && ye.Current.CompareTo(xe.Current) < 0 )
{
// do nothing - all we care here is that we advanced the y enumerator
}
if (ye.Current.Equals(xe.Current))
yield return xe.Current;
else
{ // y is now > x, so get x caught up again
while (xe.MoveNext() && xe.Current.CompareTo(ye.Current) < 0 )
{ } // again: just advance, do do anything
if (xe.Current.Equals(ye.Current)) yield return xe.Current;
}
}
}
}
If you by lambda syntax mean a real LINQ query, it looks like this:
IEnumerable<int> j =
from cItem in c
join aitem in a on cItem equals aItem
select aItem;
A lambda expression is when you use the => operator, like in:
IEnumerable<int> x = a.Select(y => y > 5);
What you have with the Union method really is a non-LINQ way of doing it, but I suppose that you mean a way of doing it without extension methods. There is hardly a one-liner for that. I did something similar using a Dictionary yesterday. You could do like this:
Dictaionary<int, bool> match = new Dictaionary<int, bool>();
foreach (int i in c) match.Add(i, false);
foreach (int i in a) {
if (match.ContainsKey(i)) {
match[i] = true;
}
}
List<int> result = new List<int>();
foreach (KeyValuePair<int,bool> pair in match) {
if (pair.Value) result.Add(pair.Key);
}