从动态Linq查询返回索引列表

时间:2016-03-28 11:57:11

标签: c# arrays linq

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

我最初采用了一些粗略且准备好的方法来获取索引列表,只需迭代原始列表并找到项目与筛选列表中的项目相等的位置,如下所示:

    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语句将结构数组投影到一个带有附加&#34;索引的新数组中。字段,执行过滤,然后从select语句中仅返回这些索引值将是微不足道的。

但是,我在如何实现这一目标方面略有一点空白。

感谢任何建议。

2 个答案:

答案 0 :(得分:0)

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

angular.module('portal', [ 
  'ui.router',
  'ceibo.components.table.export',
  'portal']); //REMOVE THIS 
})();

答案 1 :(得分:0)

它比我想象的要简单,虽然这不是我理想的解决方案,因为我必须更改查询和orderby子句的每个传入字符串表达式以包括预计的实体名称。它虽然有效,所以它现在可以用,直到我有更多的时间。

    public static int[] FilterStructs<T>(IList<T> structs, string query = "", string orderBy = "", int topN = 0) where T : struct {
        var withIndex = structs.Select((s, i) => new { index = i, item = s });
        var filteredStructs = withIndex.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 filteredStructs.Select("index").Cast<int>().ToArray();            
    }

例如,如果我之前的where子句是“value = 123”,那么它现在必须变成“item.value = 123”。