Reputation: 16685
I'm trying to construct a lambda expression that will match elements of one array with a second. Below is a simplified version of this query:
class Program
{
static void Main(string[] args)
{
string[] listOne = new string[] { "test1", "test2", "test3" };
MyClass[] listTwo = new MyClass[] { new MyClass("test1") };
string[] newVals = listOne.Where(p => listTwo.Select(e => e.Name).Equals(p)).ToArray();
//string[] newVals2 = listOne.Intersect(listTwo.Select(t => t.Name)).ToArray();
}
class MyClass
{
public MyClass(string name)
{
Name = name;
}
public string Name {get; set;}
}
}
I would expect newVals
to return an array of 1 value, but it's empty. I realise that uncommenting myVals2 would achieve the same result, but the lists of classes differ more fundamentally than shown.
Upvotes: 1
Views: 109
Reputation: 2716
You are trying to perform a join, technically you are better off simplifying your linq statement to use a join. An example is included below.
static void Main(string[] args)
{
string[] listOne = new [] { "test1", "test2", "test3" };
MyClass[] listTwo = new [] { new MyClass("test1") };
string[] newVals = (from str1 in listOne
join str2 in listTwo.Select(e => e.Name) on str1 equals str2
select str1).ToArray();
foreach (var newVal in newVals)
{
Console.WriteLine(newVal);
}
//string[] newVals2 = listOne.Intersect(listTwo.Select(t => t.Name)).ToArray();
}
class MyClass
{
public MyClass(string name)
{
Name = name;
}
public string Name { get; set; }
}
Upvotes: 0
Reputation: 52788
You probably want to perform a Join
on the 2 collections.
var q =
listOne
.Join(
listTwo,
l2 => l2,
l1 => l1.Name,
(l2, l1) => new { l2, l1, });
You can change the selector (the last parameter) to suit your needs, if it's just values from listOne for example then have (l2, l1) => l1
.
The other solutions will work, but maybe not as you would expect.
Using Linq-Objects Contains within a where clause will cause the entire of listTwo
to be iterated for each entry in listOne
.
Upvotes: 2
Reputation: 3910
How about something like this:
string[] newVals = listOne.Where(p => listTwo.Any(e => e.Name.Contains(p))).ToArray();
or to be more strict use ==
instead of Contains
.
But if you want to obtain the items that are common between the 2 why not just call .Intersect()
??
Upvotes: 1
Reputation: 33381
Try this:
string[] listOne = new string[] { "test1", "test2", "test3" };
MyClass[] listTwo = new MyClass[] { new MyClass("test1") };
string[] newVals = listOne
.Where(p => listTwo.Select(e => e.Name).Contains(p))
.ToArray();
listTwo.Select(e => e.Name)
is a IEnumerable<string>
Upvotes: 2
Reputation: 27584
You are using Equals
but you should use Contains
. You are checking wheter IEnumerable<>
is equal to p
, but you want to check if IEnumerable<>
contains p
, so replace:
string[] newVals = listOne.
Where(p => listTwo.Select(e => e.Name).Equals(p)).
ToArray();
with
string[] newVals = listOne.
Where(p => listTwo.Select(e => e.Name).Contains(p)).
ToArray();
Upvotes: 4