帮助对 except 扩展方法进行新的覆盖

发布于 2024-10-23 16:44:18 字数 929 浏览 1 评论 0原文

我想编写一个新的重写 Except< IEnumerable 的 /code>扩展方法能够内联比较器,而不是使用 IEqualityComparer。

A、B 是引用类型的集合。

类似这样的内容:

A: [1, A], [2, A], [3, A]

B: [3, B], [4, B], [5, B]

C = A.Except(B, (a,b) => a.Id == b.Id);

C: [1, A], [2, A]

我想知道您是否可以帮助我编写该方法的代码。

public static class IEnumerableExntesion
    {
        public IEnumerable<T> Except<T>(this IEnumerable<T> source, 
                                        IEnumerable<T> second, 
                                        Func<T, T, bool> predicate)
        {

        }
    }

我在想:

return source.Where (s => !second.Any(p => p.Id == s.Id));

但实际上我无法使用传递的谓词将其转换为通用解决方案!

任何帮助!

I want to write a new override of Except extension method for IEnumerable which is able to take a comparer inline instead of using IEqualityComparer.

A, B are collections of a reference type..

Something like this:

A: [1, A], [2, A], [3, A]

B: [3, B], [4, B], [5, B]

C = A.Except(B, (a,b) => a.Id == b.Id);

C: [1, A], [2, A]

I wonder if you could help me with the code of the method.

public static class IEnumerableExntesion
    {
        public IEnumerable<T> Except<T>(this IEnumerable<T> source, 
                                        IEnumerable<T> second, 
                                        Func<T, T, bool> predicate)
        {

        }
    }

I was thinking of:

return source.Where (s => !second.Any(p => p.Id == s.Id));

But actually I couldn't convert it to a generic solution using the passed predicate!

Any help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

停顿的约定 2024-10-30 16:44:18

您是否需要使用谓词进行比较,或者可以使用投影来比较投影值吗?如果是这样,那么您可以使用某种 ExceptBy 方法:

var c = a.ExceptBy(b, x => x.Id);

var r = p.ExceptBy(q, x => x.Name, StringComparer.OrdinalIgnoreCase);

// ...

public static class EnumerableExtensions
{
    public static IEnumerable<TSource> ExceptBy<TSource, TKey>(
        this IEnumerable<TSource> first, IEnumerable<TSource> second,
        Func<TSource, TKey> keySelector,
        IEqualityComparer<TKey> keyComparer = null)
    {
        if (first == null) throw new ArgumentNullException("first");
        if (second == null) throw new ArgumentNullException("second");
        if (keySelector == null) throw new ArgumentNullException("keySelector");

        return first.ExceptByIterator(second, keySelector, keyComparer);
    }

    private static IEnumerable<TSource> ExceptByIterator<TSource, TKey>(
        this IEnumerable<TSource> first, IEnumerable<TSource> second,
        Func<TSource, TKey> keySelector, IEqualityComparer<TKey> keyComparer)
    {
        var keys = new HashSet<TKey>(second.Select(keySelector), keyComparer);

        foreach (TSource item in first)
        {
            if (keys.Add(keySelector(item)))
                yield return item;
        }
    }
}

Do you need to do the comparison using a predicate or can you use a projection instead and compare the projected values? If so then you could use some sort of ExceptBy method:

var c = a.ExceptBy(b, x => x.Id);

var r = p.ExceptBy(q, x => x.Name, StringComparer.OrdinalIgnoreCase);

// ...

public static class EnumerableExtensions
{
    public static IEnumerable<TSource> ExceptBy<TSource, TKey>(
        this IEnumerable<TSource> first, IEnumerable<TSource> second,
        Func<TSource, TKey> keySelector,
        IEqualityComparer<TKey> keyComparer = null)
    {
        if (first == null) throw new ArgumentNullException("first");
        if (second == null) throw new ArgumentNullException("second");
        if (keySelector == null) throw new ArgumentNullException("keySelector");

        return first.ExceptByIterator(second, keySelector, keyComparer);
    }

    private static IEnumerable<TSource> ExceptByIterator<TSource, TKey>(
        this IEnumerable<TSource> first, IEnumerable<TSource> second,
        Func<TSource, TKey> keySelector, IEqualityComparer<TKey> keyComparer)
    {
        var keys = new HashSet<TKey>(second.Select(keySelector), keyComparer);

        foreach (TSource item in first)
        {
            if (keys.Add(keySelector(item)))
                yield return item;
        }
    }
}
但可醉心 2024-10-30 16:44:18

这应该有效:

return source.Where(s => !second.Any(p => predicate(s, p))

This should work:

return source.Where(s => !second.Any(p => predicate(s, p))
清引 2024-10-30 16:44:18
return source.Where(s => !second.Any(p => predicate(p, s)));
return source.Where(s => !second.Any(p => predicate(p, s)));
拒绝两难 2024-10-30 16:44:18

我会使用您传递的 Func 来创建通用 IEqualityComparer 并将其传递给常规 Except

public class PredicateEqualityComparer<T> : IEqualityComparer<T>
{
    private readonly Func<T, T, bool> _predicate;

    public PredicateEqualityComparer(Func<T, T, bool> predicate)
    {
        _predicate = predicate;
    }

    public bool Equals(T x, T y)
    {
        return _predicate(x, y);
    }

    public int GetHashCode(T x)
    {
        return 0;
    }
}

您的扩展方法:

public static class IEnumerableExntesion
{
    public IEnumerable<T> Except<T>(this IEnumerable<T> source, 
                                    IEnumerable<T> second, 
                                    Func<T, T, bool> predicate)
    {
        return source.Except(second, new PredicateEqualityComparer(predicate));
    }
}    

请注意,我有存根 GetHashCode 实现,最好正确实现它,但您必须为其传递另一个委托。

I would instead use your passed Func<T,T,bool> to create a generic IEqualityComparer and pass it to regular Except:

public class PredicateEqualityComparer<T> : IEqualityComparer<T>
{
    private readonly Func<T, T, bool> _predicate;

    public PredicateEqualityComparer(Func<T, T, bool> predicate)
    {
        _predicate = predicate;
    }

    public bool Equals(T x, T y)
    {
        return _predicate(x, y);
    }

    public int GetHashCode(T x)
    {
        return 0;
    }
}

Your extension method:

public static class IEnumerableExntesion
{
    public IEnumerable<T> Except<T>(this IEnumerable<T> source, 
                                    IEnumerable<T> second, 
                                    Func<T, T, bool> predicate)
    {
        return source.Except(second, new PredicateEqualityComparer(predicate));
    }
}    

Please note that I have stub GetHashCode implementation, it would be better to implement it properly but you would have to pass another delegate for it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文