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

时间:2015-10-29 14:48:52

标签: c# performance linq list large-data-volumes

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

目前我使用以下算法:

  1. 列表项
  2. 将要过滤的对象放入通用列表
  3. 对于每个过滤器规范:
    • 创建Where表达式(Expression>)
    • 使用Linq>应用表达式在哪里到对象列表
    • 获取所选对象的IEnumerable,并将它们与过滤器的描述一起存储在列表中
    • 使用Linq>删除从源列表中找到的项目。除了创建新列表以继续使用和阻止将对象放入多个子列表之外
  4. 检查工作清单中是否有(未分割的)对象
  5. 我最初的对象列表可能超过400.000个对象,我注意到过滤以及减少工作列表都需要一些时间。所以我想知道:

    1. 过滤以创建子列表最多可以在我的对象的7个属性上进行。有没有办法提高Linq的性能>哪里有选择?
    2. 有没有办法阻止项目被选入多个子列表,而不会通过使用Except或RemoveAll(可能的改进)来减少工作集合?
    3. 提前致谢!

1 个答案:

答案 0 :(得分:4)

如果您无法利用传入列表中的任何索引,那么您最好只需遍历整个列表一次,然后对项目进行分类。这样就可以避免不必要的删除除了操作,这些操作会严重损害无意义迭代和相等比较的性能。

我正在考虑以下几点:

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并返回bool。如果这还不够,那么没有什么能阻止您使用您需要的任何签名来实现自己的MyPredicate<???>

编辑:编辑代码以处理&#34; 默认存储桶&#34;哪些项目不符合任何指定的谓词。