考虑以下简化示例,该示例在搜索对象列表的代码之后建模,并通过为每个对象分配分数来对其进行排序以尝试计算相关性(实际代码中的得分细节不相关)这里):
public class MyClass
{
public string UserName { get; set; }
public string UserDescription { get; set; }
}
public static void QueryTest()
{
var somequerytext = "test";
var accounts = new List<MyClass>();
var resultsViaInt = accounts.Where( ( MyClass acct, int score ) =>
MatchInt( acct.UserName, somequerytext, ref score, 2 ) ||
MatchInt( acct.UserDescription, somequerytext, ref score, 1 )
)
.Select( ( acct, score ) => new { result = acct, score = score } )
.OrderBy( x => x.score )
.Select( x => x.result )
.ToList();
var resultsViaDouble = accounts.Where( ( MyClass acct, double score ) =>
MatchDouble( acct.UserName, somequerytext, ref score, 2.0 ) ||
MatchDouble( acct.UserDescription, somequerytext, ref score, 1.0 )
)
.Select( ( MyClass acct, double score ) => new { result = acct, score = score } )
.OrderBy( x => x.score )
.Select( x => x.result )
.ToList();
}
public static bool MatchInt( string haystack, string needle, ref int score, int weight )
{
if ( haystack.Contains( needle ) )
{
score = score + weight;
return true;
}
return false;
}
public static bool MatchDouble( string haystack, string needle, ref double score, double weight )
{
if ( haystack.Contains( needle ) )
{
score = score + weight;
return true;
}
return false;
}
由于某种原因,编译器在QueryTest()中为第二个查询抛出the following errors:
对于“帐户”变量:
'List<MyClass>' does not contain a definition for 'Where' and the best extension method overload 'Queryable.Where<MyClass>(IQueryable<MyClass>, Expression<Func<MyClass, bool>>)' requires a receiver of type 'IQueryable<MyClass>'
对于查询本身内的lambda表达式:
Delegate 'Expression<Func<MyClass, bool>>' does not take 2 arguments
如果我尝试使用double
,float
或decimal
,我会收到相同的错误。但是,使用int
可行。我可以使用稍微更大的整数而不是双精度来完成剩下的工作,但我想知道上面的代码为什么不能编译。
第二个错误看起来很奇怪,因为第一个查询的等效部分被检测(正确)为<Func<MyClass, int, bool>>
,而带有错误的查询缺少对中间参数的任何引用。
为什么它只适用于int
?
答案 0 :(得分:3)
我认为这与您所寻找的非常接近。
var resultsViaDouble = accounts
.Select(acct =>
{
double score = 0;
return new
{
match = MatchDouble(acct.UserName, somequerytext, ref score, 2.0) || MatchDouble(acct.UserDescription, somequerytext, ref score, 1.0),
score = score,
acct = acct
};
})
.Where(x => x.match)
.OrderBy(x => x.score)
.Select(x => x.acct)
.ToList();
关于OP中的方法有什么问题,我认为评论已经足够彻底地解释了它。
答案 1 :(得分:2)
有效的Where
方法的重载是:
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, int, bool> predicate
)
(List<MyClass>
是IEnumerable)
和int
参数代表序列中元素的索引
double
参数
所以你在这里错误地使用了int score
我建议你改变这样的代码:
public static double MatchDouble(string haystack, string needle, double weight )
{
return haystack.Contains( needle ) ? weight : 0;
}
var resultsViaInt = accounts
.OrderBy(
acct => MatchDouble( acct.UserName, somequerytext, 2.0 ) +
MatchDouble( acct.UserDescription, somequerytext, 1.0 )
)
.ToList();