Custom intersect in lambda

后端 未结 4 780
离开以前
离开以前 2021-02-08 01:37

I would like to know if this is possible to solve using a lambda expression:

List listOne = service.GetListOne();
List listTwo = service.Ge         


        
相关标签:
4条回答
  • 2021-02-08 02:25

    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
    
    0 讨论(0)
  • 2021-02-08 02:30
    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);
    
    0 讨论(0)
  • 2021-02-08 02:39

    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();
    
    0 讨论(0)
  • 2021-02-08 02:43
    listOne.SelectMany(x=>listTwo.Where(y=>x.Id==y.Id && x.someKey != y.someKey));
    
    0 讨论(0)
提交回复
热议问题