2016-03-28 45 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