.net 过滤大集合

.net 过滤大集合,.net,collections,filter,.net,Collections,Filter,我有一个MyClass对象的集合,需要通过17个文件的组合对其进行过滤 我实现了一个对象MyClassFilter,其中包含17个可能的字段和每个字段的条件以及一个方法: bool PassFilter(MyClass ObjectToEvaluate) { return PassFilterVal(this.Workstream, ObjectToEvaluate.WorkStream) && PassFilterVal(this.AssignedTo, Objec

我有一个MyClass对象的集合,需要通过17个文件的组合对其进行过滤

我实现了一个对象MyClassFilter,其中包含17个可能的字段和每个字段的条件以及一个方法:

bool PassFilter(MyClass ObjectToEvaluate)
{
  return PassFilterVal(this.Workstream, ObjectToEvaluate.WorkStream)
    && PassFilterVal(this.AssignedTo, ObjectToEvaluate.AssignedTo)
    && PassFilterVal(this.ProcessingGroup, ObjectToEvaluate.ProcessingGroup)
    && PassFilterVal(this.ScheduledStart, ObjectToEvaluate.ScheduledStart)
    && PassFilterVal(this.EntityName, ObjectToEvaluate.EntityName)
    && PassFilterVal(this.TaskIDs, ObjectToEvaluate.TaskID)
    && PassFilterVal(this.ElementIDs, ObjectToEvaluate.EntityID)
    && PassFilterVal(this.MappingIDs, ObjectToEvaluate.MappingID)
    && PassFilterVal(this.EntityStatus, ObjectToEvaluate.EntityStatus)
    && PassFilterVal(this.EntityType, ObjectToEvaluate.EntityType)
    && PassFilterVal(this.NumberOfSteps, ObjectToEvaluate.ListOfSteps.Count)
    && PassFilterVal(this.NumberOfDependancies, ObjectToEvaluate.ListOfParentDependancies.Count)
    && PassFilterVal(this.NumberOfOpenIssues, ObjectToEvaluate.ListOfAllIssues.CountOpen)
    && PassFilterVal(this.NumberOfRequirementsLinked, ObjectToEvaluate.RequierementsLinked)
    ;
}
我的收藏有一个方法

ListOfMyClass FilterList(MyClassFilter Filter){
    ListOfMyClass FilteredList = new ListOfMyClass();
    foreach (MyClass Task in this)
    {
      if (Filter.TaskPassFilter(Task))
        FilteredList.Add(Task);
    }
    return FilteredList;
}
只要收集的对象很小,它就可以正常工作,但当我有500个对象时,它就开始变得非常缓慢。我在网上搜索过,但所有的例子都是在集合中逐个对象,并按字段询问是否通过

对于如何提高绩效有何建议

谢谢你

我提议给你一个可爱的小把戏:

也许您可以实现
.CompareTo
(或任何语言的等价物;我假设是.NET),这样“更接近”的匹配就在最上面。然后,您只需使用一个按insert排序的集合,所有这些都会发生在您身上

通过这种方式,你可以循环所有项目,一旦你发现一个不匹配的项目,就停止,因为你知道下面所有不匹配的项目


我很想看看结果如何。但是,也许其他人会有更好的建议(如果出于某种原因这很愚蠢,我准备看起来像个傻瓜)。

这不应该太慢,除非你的比较慢

扫描500个物体应该非常快(当然你没有提到“慢”是什么,也没有提到你的硬,但即使如此…)

由于方法调用的原因,您的PassFilterVal将“更昂贵”,而不是让比较结果排成一行,但由于它们的价格都是一样的,我想我们还是坚持现有的价格

您可以对参数进行排序,以便最有选择性的参数排在第一位

这里的目标是利用ANDs的短路来尽快转储,从而限制实际比较的数量

您可以做的另一件事是首先针对“最常见的查询”对其进行优化

是否始终使用所有标准?如果没有,您应该将比较限制为实际使用的比较。在这种情况下,相等实际上是昂贵的(17个方法调用和17个“未知”复杂性的比较)。如果您有某种通配符或“不在乎”值,您可以尝试跳过这些值进行比较


另一个想法是根据所有17个标准对元素进行排序。然后使用二进制搜索匹配所有17个字段的元素,最后迭代其余元素,直到它们停止匹配您的条件。当然,您需要始终保持列表正确排序,但一旦排序,它将是一个二进制插入,这将非常快。如果您阅读的内容比添加到列表中的内容多得多,那么这应该是一个净收益。

如果没有更多的上下文,实际上不可能提出性能如此缓慢的原因。不过,我可以提供一些线索。如果500个项目的速度变慢,那么可能有一个O(N^2)算法(或者更糟)潜伏在那里的某个地方。我猜您的一个或多个属性在每次比较期间都会遍历一大组数据

对于C#中的属性,很难知道它们是如何实现的,例如,像NumberOfDependencies这样的无名小卒每次调用时都会遍历一个非常大的图。或者它可能正在生成一个列表来统计依赖项。如果可能,我会计算这些值一次,并将它们存储在类中(如果可能)。然而,当我看到使用它的上下文时,我看到了另一个问题:

PassFilterVal(this.NumberOfDependancies, ObjectToEvaluate.ListOfParentDependancies.Count
如果“ListofParentDependences”是一个IEnumerable,那么每次调用它时,您都要遍历所有依赖项的列表,以计算数量

你的过滤功能,在性能方面是好的。为了优雅,以及可能适度提升性能,我将按如下方式实现它

IEnumerable<MyClass> FilterList(MyClass filter) {
    foreach (MyClass task in this)
       if (filter.TaskPassFilter(task))
         yield return task;
}     
IEnumerable过滤器列表(MyClass过滤器){
foreach(此示例中的MyClass任务)
if(filter.TaskPassFilter(任务))
收益回报任务;
}     

你应该为你正在使用的语言添加一个标签……我耐心地等待有人解释为什么这是个坏主意。我很想知道。我没有投你反对票,但也许是一个代码示例?我是说,我明白你的意思,但我不明白。同意拉诺莫尔的说法。还有,为什么这比OP中的链式短路布尔值更好(嗯,可能是灵活性)