应用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执行免费文本搜索…^^有意义吗?
这至少是一个更大的图景,这个问题主要处理的是能够指定我要索引的字段,以便我以后可以使用它们,就像这里提到的。
比如:
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算法。相同的分布式形式通常用于文本搜索中的关键字标识,其中您希望构建(搜索词)->(包含文档的列表)的索引。