问题
I would like to know if this is possible to solve using a lambda expression:
List<Foo> listOne = service.GetListOne();
List<Foo> listTwo = service.GetListTwo();
List<Foo> result = new List<Foo>();
foreach(var one in listOne)
{
foreach(var two in listTwo)
{
if((one.Id == two.Id) && one.someKey != two.someKey)
result.Add(one);
}
}
回答1:
Sure you can! You can use this overload of Linq's Intersect
extension method which takes an IEqualityComparer<T>
, like this:
public class FooComparer : IEqualityComparer<Foo>
{
public bool Equals(Foo x, Foo y)
{
return x.Id == y.Id && x.someKey != y.someKey;
}
public int GetHashCode(Foo x)
{
return x.Id.GetHashCode();
}
}
...
var comparer = new FooComparer();
List<Foo> listOne = service.GetListOne();
List<Foo> listTwo = service.GetListTwo();
List<Foo> result = listOne.Intersect(listTwo, comparer).ToList();
回答2:
listOne.SelectMany(x=>listTwo.Where(y=>x.Id==y.Id && x.someKey != y.someKey));
回答3:
You may try:
var result = listOne.Join(listTwo,
(one) => one,
(two) => two,
(one, two) => one,
new MyFooComparer());
Where MyFooComparer
could look like:
class MyFooComparer : IEqualityComparer<Foo>
{
public bool Equals(Foo x, Foo y)
{
return x.Id == y.Id && x.someKey != y.someKey;
}
public int GetHashCode(Foo obj)
{
return obj.Id.GetHashCode();
}
}
[UPDATE]
I was curious about the performance of Intersect
vs. Join
so I made a small performance comparison between my solution and @p.s.w.g.'s (listOne
and listTwo
have 10 items each):
var comparer = new MyFooComparer();
var sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 100000; i++)
{
var result1 = listOne.Intersect(listTwo, comparer).ToList();
}
Console.WriteLine("Intersect: {0}",sw.Elapsed);
sw.Restart();
for (int i = 0; i < 100000; i++)
{
var result = listOne.Join(listTwo,
(one) => one,
(two) => two,
(one, two) => one,
comparer);
}
Console.WriteLine("Join: {0}", sw.Elapsed);
The output:
Intersect: 00:00:00.1441810
Join: 00:00:00.0037063
回答4:
var result = from one in listOne
join two in listTwo on one.Id equals two.Id
where one.SomeKey != two.SomeKey
select one;
Update: It seems that some people feel that this is not answering the question, as it supposedly is not using lambdas. Of course it is, it's just using the friendly query syntax.
Here's the exact same code, only less readable:
var result =
listOne.Join(listTwo, one => one.Id, two => two.Id, (one, two) => new { one, two })
.Where(p => p.one.someKey != p.two.someKey)
.Select(p => p.one);
来源:https://stackoverflow.com/questions/19583793/custom-intersect-in-lambda