如何有效地比较列表?

时间:2017-02-23 10:46:28

标签: c# entity-framework linq bigdata

我目前正在使用asp.net中的Web应用程序。在某些api调用中,有必要将ListA与ListB的列表进行比较,以确定ListA是否具有ListB中任何List的相同元素。换句话说:如果ListA包含在ListB中。

使用EF-Code-First数据库的Linq查询这两个集合。 ListB有一个匹配的List或者没有,只有一个。在最坏的情况下,ListB有数百万个元素,因此比较需要可扩展。

我没有做嵌套的foreach循环,而是寻找纯粹的linq查询,这将让db完成工作。 (在我考虑多列索引之前)

说明结构:

//In reality Lists are queried of EF 
var ListA = new List<Element>();
var ListB = new List<List<Element>>(); 
List<Element> solution;
bool flag = false;
foreach (List e1 in ListB) {
   foreach(Element e2 in ListA) {
        if (e1.Any(e => e.id == e2.id)) flag = true;
        else {
             flag = false;
             break;
        }
    }
        if(flag) {
           solution = e1;
           break;
        }
}

更新结构

由于它是EF数据库,我将提供相关的对象结构。我不确定我是否可以发布实际代码,所以这个例子仍然是通用的。

//List B
class Result {
       ...
       public int Id;

       public virtual ICollection<Curve> curves; 

       ...
}

class Curve {
       ...
       public int Id;

       public virtual Result result;
       public int resultId;

       public virtual ICollection<Point> points;
       ...
}
public class Point{
    ...
    public int Id;
    ...
}

控制器(用于api-call)想要提供正确的Curve-Object。为了识别正确的对象,提供了一个过滤器(ListA)(实际上是一个曲线对象) 现在需要将过滤器(ListA)与结果中的曲线列表(ListB)进行比较 比较曲线的唯一方法是比较两者都有的。 (因此事实上比较列表) 曲线大约有1到50个点。 结果可以有大约500.000.000曲线

这里可以通过Object-Identity进行比较,因为所有对象(甚至是过滤器)都会被重新查询db。

我正在寻找一种方法来实现这种机制,而不是如何解决这种情况。 (例如,通过使用多列索引(改变表格))

(用于说明目的):

class controller {
    ...
    public Response serveRequest(Curve filter) {
         foreach(Curve c in db.Result.curves) {
               if(compare(filter.points , c.points)) return c;

         }
    }
}

1 个答案:

答案 0 :(得分:0)

由于性能受到关注,我建议在比较Ex -

之前将listA转换为lookup / dictionary
var listALookup = listA.ToLookup(item => item.Id);
var result = listB.FirstOrDefault(childList => childList.Count == listA.Count && childList.All(childListItem => listALookup.Contains(childListItem.Id)));

Lookup.Contain是O(1)而List.Contains是O(n)

更好的选择是在db级别执行此比较,以减少加载不必要的数据。