如何有效地从(最初)大量对象列表中过滤对象

How to efficiently filter objects out of an (initially) large list of objects

我需要将大量复杂(20 多个属性)对象过滤成多个子列表。要创建子列表,我有一个过滤器规范列表。要求是:a) 不允许一个项目成为两个子列表的一部分,并且 b) 必须能够在处理完成后获得所有未分割的项目。

目前我使用以下算法:

  1. 列表项
  2. 将要过滤的对象放在通用列表中
  3. 对于每个过滤器规格:
    • 创建 Where 表达式 (表达式>)
    • 使用 Linq > Where 将表达式应用于对象列表
    • 获取所选对象的结果 IEnumerable 并将它们与过滤器的描述一起存储在列表中
    • 使用 Linq > Except 从源列表中删除找到的项目以创建一个新列表以继续使用并防止将一个对象放入多个子列表中
  4. 检查工作列表中是否有静止(未分割)的对象

我的初始对象列表可能超过 400.000 个对象,我注意到过滤和减少工作列表都需要一些时间。所以我想知道:

  1. 创建子列表的过滤发生在我的对象的最多 7 个属性上。有没有办法提高 Linq > Where 选择的性能?
  2. 有没有办法在不使用 Except 或 RemoveAll 减少工作集合的情况下防止项目被选入多个子列表(可能的改进)?

提前致谢!

如果您无法利用您尝试分类的传入列表中的任何索引,那么您最好只遍历整个列表仅一次并根据您的需要对项目进行分类走。通过这种方式,您可以避免不必要的 removeexcept 操作,这些操作会通过无意义的迭代和相等比较严重损害性能。

我一直在考虑以下内容:

public static IDictionary<string, List<T>> Classify<T>(this IEnumerable<T> items, IDictionary<string, Predicate<T>> predicates, out List<T> defaultBucket)
{
    var classifiedItems = new Dictionary<string, List<T>>(predicates.Count);
    defaultBucket = new List<T>();

    foreach (var predicate in predicates)
    {
        classifiedItems.Add(predicate.Key, new List<T>()); 
    }

    foreach (var item in items)
    {
        var matched = false;

        foreach (var predicate in predicates)
        {
            if (predicate.Value(item))
            {
                matched = true;
                classifiedItems[predicate.Key].Add(item);
                break;
            }
        }

        if (!matched)
        {
            defaultBucket.Add(item);
        }
    }

    return classifiedItems;
}

任何给定的 predicate 都可以像您需要的那样复杂。唯一的条件是它接受一个 T 和 returns 一个 bool。如果这还不够,没有什么可以阻止您使用您需要的任何签名实现您自己的 MyPredicate<???>

EDIT:编辑代码以处理“默认存储桶”,其中项目不符合任何指定谓词去吧。