自定义在 lambda 中相交

本文关键字:lambda 自定义 | 更新日期: 2023-09-27 18:36:47

我想知道是否可以使用 lambda 表达式解决这个问题:

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);
    }
}

自定义在 lambda 中相交

当然可以!您可以使用 Linq 的 Intersect 扩展方法的重载,该方法需要IEqualityComparer<T>,如下所示:

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();
listOne.SelectMany(x=>listTwo.Where(y=>x.Id==y.Id && x.someKey != y.someKey));

你可以试试:

var result = listOne.Join(listTwo,
    (one) => one,
    (two) => two,
    (one, two) => one,
    new MyFooComparer());

MyFooComparer可能如下所示:

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();
    }
}

[更新]

我对Intersect与的表现感到好奇。 Join所以我在我的解决方案和 @p.s.w.g. 的解决方案之间做了一个小的性能比较(listOnelistTwo 各有 10 个项目):

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);

输出:

Intersect: 00:00:00.1441810
Join:      00:00:00.0037063
var result = from one in listOne
             join two in listTwo on one.Id equals two.Id
             where one.SomeKey != two.SomeKey
             select one;

更新:似乎有些人觉得这没有回答这个问题,因为它应该没有使用 lambda。当然是,它只是使用友好的查询语法。

这是完全相同的代码,只是可读性较差:

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);