过滤Linq EXCEPT属性

Wes*_*ley 38 c# linq

这可能看起来很愚蠢,但我发现Except在linq中使用的所有示例都使用两个列表或仅包含字符串或整数的数组,并根据匹配过滤它们,例如:

var excludes = users.Except(matches);
Run Code Online (Sandbox Code Playgroud)

我想使用exclude来保持我的代码简短,但似乎无法找到如何执行以下操作:

class AppMeta
{
    public int Id { get; set; }
}

var excludedAppIds = new List<int> {2, 3, 5, 6};
var unfilteredApps = new List<AppMeta>
                         {
                           new AppMeta {Id = 1},
                           new AppMeta {Id = 2},
                           new AppMeta {Id = 3},
                           new AppMeta {Id = 4},
                           new AppMeta {Id = 5}
                         }
Run Code Online (Sandbox Code Playgroud)

如何获取AppMeta过滤器列表excludedAppIds

Col*_*inE 67

尝试一个简单的查询位置

var filtered = unfilteredApps.Where(i => !excludedAppIds.Contains(i.Id)); 
Run Code Online (Sandbox Code Playgroud)

except方法使用相等,您的列表包含不同类型的对象,因此它们包含的任何项都不相同!

  • 为了提高效率,建议将`excludedAppIds`存储为`HashSet`,否则你有一个'O(N²)`算法遍历排除列表的次数与源中的元素一样多. (7认同)
  • @ nmit026哈希集使用元素的哈希码进行树搜索。因此,搜索匹配项时不必迭代集合。结果是O(N *哈希深度)aka O(N) (2认同)

dot*_*NET 13

ColinE的答案简单而优雅.如果您的列表较大并且排除了排除的应用列表,则BinarySearch<T>可能会比以前更快Contains.

例:

unfilteredApps.Where(i => excludedAppIds.BinarySearch(i.Id) < 0);
Run Code Online (Sandbox Code Playgroud)

  • `!(a> = b)`是一种有趣的方式来说'a <b`;) (2认同)

Sco*_*ott 13

我使用Except的扩展方法,允许你将苹果与橘子进行比较,只要它们都有一些可以用来比较它们的常用方法,比如Id或Key.

public static class ExtensionMethods
{
    public static IEnumerable<TA> Except<TA, TB, TK>(
        this IEnumerable<TA> a,
        IEnumerable<TB> b,
        Func<TA, TK> selectKeyA,
        Func<TB, TK> selectKeyB, 
        IEqualityComparer<TK> comparer = null)
    {
        return a.Where(aItem => !b.Select(bItem => selectKeyB(bItem)).Contains(selectKeyA(aItem), comparer));
    }
}
Run Code Online (Sandbox Code Playgroud)

然后使用这样的东西:

var filteredApps = unfilteredApps.Except(excludedAppIds, a => a.Id, b => b);
Run Code Online (Sandbox Code Playgroud)

扩展与ColinE的答案非常相似,它只是打包成一个整齐的扩展,可以重复使用,而不需要太多的精神开销.


azu*_*eca 11

这就是LINQ所需要的

public static IEnumerable<T> Except<T, TKey>(this IEnumerable<T> items, IEnumerable<T> other, Func<T, TKey> getKey) 
{
    return from item in items
            join otherItem in other on getKey(item)
            equals getKey(otherItem) into tempItems
            from temp in tempItems.DefaultIfEmpty()
            where ReferenceEquals(null, temp) || temp.Equals(default(T))
            select item; 
}
Run Code Online (Sandbox Code Playgroud)


sca*_*tag 7

List<AppMeta>从排除的List 构造a 并使用Except Linq运算符.

var ex = excludedAppIds.Select(x => new AppMeta{Id = x}).ToList();                           
var result = ex.Except(unfilteredApps).ToList();
Run Code Online (Sandbox Code Playgroud)


Fre*_*lén 5

从 .NET 6 开始,现在有一个ExceptBy专门为此设计的内置程序:

var filtered = unfilteredApps.ExceptBy(excludedAppIds, a => a.Id); 
Run Code Online (Sandbox Code Playgroud)