Custom intersect in lambda

回眸只為那壹抹淺笑 提交于 2019-12-03 17:07:30

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!