我想为IEnumerable
编写一个新的Except
扩展方法覆盖,它可以采用内联比较器而不是使用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));
但实际上我无法使用传递的谓词将其转换为通用解决方案!
任何帮助!
答案 0 :(得分:2)
这应该有效:
return source.Where(s => !second.Any(p => predicate(s, p))
答案 1 :(得分:2)
return source.Where(s => !second.Any(p => predicate(p, s)));
答案 2 :(得分:2)
您是否需要使用谓词进行比较,还是可以使用投影来比较投影值?如果是这样,那么您可以使用某种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;
}
}
}
答案 3 :(得分:0)
我会使用您传递的Func<T,T,bool>
来创建通用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
存根,最好正确实施它,但你必须为它传递另一个代理。