应用Linq函数单个元素级别的键选择器

本文关键字:元素 选择器 单个 函数 Linq 结果 应用 | 更新日期: 2023-09-27 18:17:54

很抱歉,如果标题误导了,我不知道如何描述这个

我的最终目标是有IQueryable<T>的扩展方法和某种形式的表达式(例如见下面),允许我必须返回IQueryable<EntityIndex<T>>(或类似的),其中包含Entity字段中的原始T,以及包含由某种形式的表达式描述的元素的数组/枚举。

我知道这不是很有意义,希望在一个例子之后它会…

这是我目前为止写的:

class EntityIndex<T, TKey>
{
    T Entity { get; set; }
    // Doesn't have to be IEnumerable, whatever is easier
    IEnuermable<TKey> Index { get; set; }
}
static class Elsewhere
{
    [Extension()]
    public IQueryable<EntityIndex<T, TKey>> IndexBy<T, TKey>(this IQueryable<T> source, Expression<Func<T, TKey[]>> indexSelector)
    {
        return source.Select(n => new EntityIndex<T, TKey> {
            Entity = n,
            Index = new T[] { n }.Select(indexSelector)
        });
    }
}

注意:上面的不编译,它只是在那里试图显示我想要实现的目标。

我已经使用了标准选择器,但次优的是,必须任意创建一个T数组对'Index'属性的赋值,以便能够应用选择器。我希望一个更好的参数选择可以解决这个问题,但可能不是。主要问题是这不会编译,所以如果有一个小的调整,将允许它的工作,这对我来说很好,如果你能理解我的胡言乱语,理解我在试图做什么,并且碰巧知道一个更好的方法去做它,我将非常感激。

理想情况下,我需要L2S引擎能够理解解决方案,我不相信上面的解决方案是由于引入了EntityIndex类,但我希望它能将其视为匿名类。

编辑:

说得好,达米安,更大的图景可能更容易描述…

我想要一个接受表达式的扩展方法,表达式应该描述实体上的哪些字段要索引,该表达式将在该特定表达式之后使用,以允许将标准(where子句)应用于选定的字段。

长话短说,在代码中的许多地方,我们都有一个通配符字符串搜索。如果我有一个带有Property1, Property2, Property3等的EntityA,那么看到如下代码是很常见的:

手写体,稍有错别字

public string[] WildcardSearch(string prefixText, int count)
{
    string searchTerm = prefixText.Replace(wildcard, string.Empty);
    if (prefixText.StartsWith(wildcard) && prefixText.EndsWith(wildcard)) {
        return entitySet.Where(n => n.Property1.Contains(searchTerm) || n.Property2.Contains(searchTerm)).Select(n => n.Property3).ToArray();
    } else if (prefixText.StartsWith(wildcard)) {
        return entitySet.Where(n => n.Property1.EndsWith(searchTerm) || n.Property2.EndsWith(searchTerm)).Select(n => n.Property3).ToArray();
        // you get the picture, same with EndsWith, no wildcards defaults to contains...
    }
}
编辑:

进一步澄清-使用上面的wildcarsearch作为一个例子,我希望能够有一个选择器如下或类似:

Func<EntityA, IEnumerable<string>> indexSelector = n => new string[] {
    n.Property1,
    n.Property2
};
// Alternatively, a ParamArray of keySelector might work?
Func<EntityA, string>[] keySelectors = new Func<EntityA, string>[] {
    n => n.Property1,
    n => n.Property2
};

给定一个描述要搜索实体上哪些字段的适当表达式,返回如上所示的IQueryable<EntitySearch<T>>,我希望能够应用一个标准,类似于:

Func<EntitySearch<T>, bool> criterion = n => false;
if (wildcardIsContains) {
    criterion = n => n.Values.Any(x => x.Contains(searchTerm));
} else if (wildCardIsStartsWith) {
    criterion = n => n.Values.Any(x => x.Contains(searchTerm));
    //etc
}

考虑到顶部的扩展,我无法工作,这个标准逻辑,我应该能够采取IQueryable<T>,选择一些字段,并在字段上应用适当的通配符搜索,最后再次返回IQueryable<T>添加了过滤。

谢谢¬!

如果你需要更多的信息/澄清,请评论…

编辑:说得好@subkamren,谢谢你的兴趣。一些非通用的例子可能有用。我将起草一些东西,并很快添加它们。目前,根据你的评论,我想澄清一下……

给定一个IQueryable<Animal>我想要一个扩展,允许我选择我打算搜索/索引的动物字段。例如Animal.Description, Animal.Species.Name等。这个扩展应该返回类似IIndexedQueryable<Animal>的东西。这就是我在上面的问题中试图解决的问题。我所提到的更全面的情况是,如果你愿意帮助我,我会非常高兴,如下:

IIndexedQueryable<T>接口反过来,我想要一个扩展,可以采取string搜索词。扩展应该解析搜索词中的通配符,用必要的条件扩展原始IQueryable,以便在索引字段上执行搜索,并再次返回IQueryable<T>

我很感激这可以在一个步骤中完成,但我希望这样做,以便以后我可以考虑添加适用于IIndexedQueryable<T>的第三个扩展方法,允许我使用SQL Server执行免费文本搜索…^^有意义吗?

这至少是一个更大的图景,这个问题主要处理的是能够指定我要索引的字段,以便我以后可以使用它们,就像这里提到的。

应用Linq函数<T,结果>单个元素级别的键选择器

比如:

public static IEnumerable<EntityIndex<T, Y>> IndexBy<T, Y>(this IEnumerable<T> entities, Func<T, Y> indexSelector) {
    return entities.Select(e => new EntityIndex<T, Y> { Entity = e, IndexValue = indexSelector(e) });
}

注意使用TIndexType(这里称为Y)一般定义EntityIndex很重要,因为您无法提前知道索引是什么。泛型的使用允许Y是一个枚举,因此下面的代码可以用作索引选择器:

// Assuming Animal has attributes "Kingdom", "Phylum", "Family", "Genus", "Species"
// this returns an enumeration of EntityIndex<Animal, String[]>
var animalsClassified = someAnimals.IndexBy(a => new String[] { a.Kingdom, a.Phylum, a.Family, a.Genus, a.Species });

EDIT(添加更多细节):

使用上面的代码,您可以根据唯一的索引值对结果进行分组:

var animalClassifications = animalsClassified
                                .SelectMany(ac => ac.IndexValue.Select(iv => new { IndexValue = iv, Entity = ac.Entity }))
                                .GroupBy(kvp => kvp.IndexValue)
顺便说一下,我在这里描述的是(一种非常简化的)由谷歌推广的MapReduce算法。相同的分布式形式通常用于文本搜索中的关键字标识,其中您希望构建(搜索词)->(包含文档的列表)的索引。