2016-03-28 54 views
0

我有一个过滤器方法,它采用结构的通用数组,执行查询和/或orderby和/或将表达式作为使用动态linq的字符串,并返回匹配索引列表,然后由外部程序使用。动态LINQ查询返回索引列表

我最初采取了一下粗略的方法来获取索引列表,简单地通过循环原始名单,并找到其中的项目是等于在过滤列表中的项目如下:

public static int[] FilterStructs<T>(IList<T> structs, string query = "", string orderBy = "", int topN = 0) where T : struct {    
     var filteredStructs = structs.AsQueryable(); 
     if (!string.IsNullOrEmpty(query)) filteredStructs = filteredStructs.Where(query); 
     if (!string.IsNullOrEmpty(orderBy)) filteredStructs = filteredStructs.OrderBy(orderBy); 
     if (topN > 0) filteredStructs = filteredStructs.Take(topN); 
     return GetArrayIndexList(structs, filteredStructs.ToArray()); 
    } 

    private static int[] GetArrayIndexList<T>(IList<T> arrMain, T[] arrFiltered) where T : struct { 
     List<int> indexes = new List<int>(); 
     for (int i = 0; i < arrFiltered.Length; i++) { 
      for (int j = 0; j < arrMain.Count; j++) { 
       if (arrMain[j].Equals(arrFiltered[i])) { 
        indexes.Add(j); 
        break; 
       } 
      } 
     } 
     return indexes.ToArray(); 
    } 

但是,当结构数组中有几千个项目时,这会变得非常慢。

我最想做的事情是,最初使用动态select语句将结构数组投影到具有附加“索引”字段的新数组中,执行过滤,然后仅从这些索引值返回选择语句将是微不足道的。

但是,我对如何实现这一点留有一点空白。

任何意见表示赞赏。

回答

0

这是比我想象的简单,虽然这不是我的理想解决方案,因为我需要改变的查询和排序依据子句每个传入的字符串表达式,包括投影实体名称。它可以工作,所以它现在会做,直到我有更多的时间。例如,如果我以前的where子句是“value = 123”,它现在必须变成“item.value = 123”。

+0

顺便提一句,这可以减少从使用GetArrayIndexList方法从大约1500ms到40ms的执行时间。 – Hoodlum

0

如果我理解正确,过滤后的数组元素保证存在于原始数组中,因此您可以用以下代替GetArrayIndexList主体。

private static int[] GetArrayIndexList<T>(IList<T> arrMain, T[] arrFiltered) where T : struct 
    { 
     return arrFiltered.Select(c=> arrMain.IndexOf(c)).ToArray(); 
    } 
+0

感谢您的支持。不过,我认为IndexOf将使用默认的相等比较器,这是导致方法变慢的原因。尽管这个代码少得多,但对于4000个物品的阵列来说,它仍然花费1秒以上的时间。 – Hoodlum