gpt4 book ai didi

c# - 没有 equals 进行外部连接的最干净的方法是什么?

转载 作者:行者123 更新时间:2023-12-02 22:02:50 25 4
gpt4 key购买 nike

我有两个列表,我需要在第一个列表中找到第二个列表中缺少的项目,但我只能将它们与 bool 函数进行比较。

class A
{
internal bool Matching(A a)
{
return true;
}
}

class OuterMatch
{
List<A> List1 = new List<A>();
List<A> List2 = new List<A>();

void BasicOuterJoin()
{
// textbook example of an outer join, but it does not use my Matching function
var missingFrom2 = from one in List1
join two in List2
on one equals two into matching
from match in matching.DefaultIfEmpty()
where match == null
select one;
}

void Matching()
{
// simple use of the matching function, but this is an inner join.
var matching = from one in List1
from two in List2
where one.Matching(two)
select one;
}

void MissingBasedOnMatching()
{
// a reasonable substitute for what I'm after
var missingFrom2 = from one in List1
where (from two in List2
where two.Matching(one)
select two)
.Count() == 0
select one;
}

MissingBasedOnMatching 给了我正确的结果,但它在视觉上不像 BasicOuterJoin 那样明显是外部连接。有没有更清晰的方法来做到这一点?

有一种采用比较运算符的 GroupJoin 形式,但我不清楚是否有办法使用它来进行外部联接。

最佳答案

我一直在使用一些有用的(而且很短!)代码 from a blog by Ed Khoze .

他发布了一个方便的类,它提供了一个适配器,以便您可以将 Enumerable.Except() 与 lambda 一起使用。

一旦你有了这段代码,你就可以使用 Except() 来解决你的问题了:

var missing = list1.Except(list2, (a, b) => a.Matching(b));

这是一个完整的可编译示例。感谢 Ed Khoze 的 LINQHelper 类:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Demo
{
class A
{
public int Value;

public bool Matching(A a)
{
return a.Value == Value;
}

public override string ToString()
{
return Value.ToString();
}
}

class Program
{
void test()
{
var list1 = new List<A>();
var list2 = new List<A>();

for (int i = 0; i < 20; ++i) list1.Add(new A {Value = i});
for (int i = 4; i < 16; ++i) list2.Add(new A {Value = i});

var missing = list1.Except(list2, (a, b) => a.Matching(b));

missing.Print(); // Prints 0 1 2 3 16 17 18 19
}

static void Main()
{
new Program().test();
}
}

static class MyEnumerableExt
{
public static void Print<T>(this IEnumerable<T> sequence)
{
foreach (var item in sequence)
Console.WriteLine(item);
}
}

public static class LINQHelper
{
private class LambdaComparer<T>: IEqualityComparer<T>
{
private readonly Func<T, T, bool> _lambdaComparer;
private readonly Func<T, int> _lambdaHash;

public LambdaComparer(Func<T, T, bool> lambdaComparer) :
this(lambdaComparer, o => 0)
{
}

private LambdaComparer(Func<T, T, bool> lambdaComparer, Func<T, int> lambdaHash)
{
if (lambdaComparer == null)
throw new ArgumentNullException("lambdaComparer");
if (lambdaHash == null)
throw new ArgumentNullException("lambdaHash");
_lambdaComparer = lambdaComparer;
_lambdaHash = lambdaHash;
}
public bool Equals(T x, T y)
{
return _lambdaComparer(x, y);
}
public int GetHashCode(T obj)
{
return _lambdaHash(obj);
}
}

public static IEnumerable<TSource> Except<TSource>
(
this IEnumerable<TSource> enumerable,
IEnumerable<TSource> second,
Func<TSource, TSource, bool> comparer
)
{
return enumerable.Except(second, new LambdaComparer<TSource>(comparer));
}
}
}

关于c# - 没有 equals 进行外部连接的最干净的方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16597818/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com