query = Files
.Where(file => file.Fileinfo.Name.ToUpper().Contains(textBox1.Text.ToUpper()))
.Take(7).ToList();
我讨厌问这个问题,但我根本没有任何进展!这应该是一项微不足道的任务,但我没有任何运气。
上述查询需要搜索文件名列表。它会将搜索结果返回到列表中,其中包含前7个最相关的结果。该事件发生在“KeyPress
”。
虽然,它非常不经常,但也有一些非常奇怪的结果。
例如:如果我的列表中的项目具有名称,则为:“ZeroWidthSplit
”
如果我的文本框包含“Z
”,则可以正常工作。如果它包含ZE
则有效。如果它包含“ZER
”,它仍会显示。
如果我输入ZERO
,它会从搜索结果中消失!
所以我想我的问题是:如何搜索文件列表,并使其返回前7个最相关的结果。
哦,如果只有4个相关结果,那也没关系。限制只有7个。
另一个例子:
F.x如果我将“sum of
”写为搜索查询。它返回:
如果我写“sum of p
”,则返回:
如果我写“sum of c
”,则不返回任何内容......
我可以给你更多奇怪的例子。
答案 0 :(得分:4)
这个错误听起来确实很奇怪,但正如Konamiman指出的那样,虽然我不喜欢使用ToUpper或ToLower,但一点点重构都不会受到影响。我将按以下方式进行:
string theText = textBox1.Text;
query = Files
.Where(file => file.Fileinfo.Name.IndexOf(theText,
StringComparison.OrdinalIgnoreCase) != -1)
.Take(7).ToList();
答案 1 :(得分:2)
您的方案中如何定义“最相关”? 如果你只使用Contains,那么结果会错过许多与精确子字符串形式不匹配的“相关”结果。
您期待什么样的输入? 如果输入只是一个单词,那么这个算法可能适合你:
适应度应计算为 最长公共子串的长度 在...中找到的目标字符串 输入字符串,除以长度 目标字符串。例如,HPPLE 与APPLE相比得分为.8, 自APPLE最长的子串 在HPPLE中找到4个字母长, 这是APPLE长度的.8。 另外,惩罚得分 对于每个无关字母,输入字符串的长度为0.1 目标字符串。例如。哈普勒 与APPLE相比得分为.9, 因为它长1个字母,而且 否则有完整的子串 苹果。请注意,这样做 候选词可能有 负分。
当然,还有很多其他更好的算法来计算距离。 如果输入可能包含多个单词,那么您可能最好使用其他算法来计算字符串之间的“距离”。
嗯......你的原始查询没有对结果进行排序,所以你没有选择前7个最相关的结果,你只是按顺序取得前7个结果。
总结一下,这可能适合你:
using System;
using System.Collections.Generic;
using System.Linq;
public static class StringDistanceUtil {
/// <summary>
/// Returns the longest common substring of the given two arguments.
/// </summary>
/// <param name="first">
/// the first string
/// </param>
/// <param name="second">
/// the second string
/// </param>
/// <returns>
/// the longest common substring of the given two arguments
/// </returns>
public static string LongestCommonSubstringWith(this string first, string second) {
// could have used dynamic programming, or generalized suffix tree
// to solve the LCS problem, but here we'll just stick to simplicity
var start = 0; // The start in a of the longest found so far
var len = 0; // The length of the longest found so far
for (var i = 0; i < first.Length - len; ++i) {
for (var j = first.Length - i; j > len; --j) {
if (second.Contains(first.Substring(i, j))) {
start = i;
len = j;
break; // Exit the inner loop
}
}
}
return first.Substring(start, len);
}
/// <summary>
/// Returns the distance of two strings.
/// </summary>
/// <param name="str">
/// a string
/// </param>
/// <param name="target">
/// the target string
/// </param>
/// <returns>
/// the distance from a string to the target string
/// </returns>
public static double DistanceFrom(this string str, string target) {
var strLen = str.Length;
var targetLen = target.Length;
var ratio = str.LongestCommonSubstringWith(target).Length
/ (double) targetLen;
var penalty =
(strLen > targetLen) ?
(0.1 * (strLen - targetLen))
: 0;
return ratio - penalty;
}
static void Main(string[] args) {
var list = new List<string> {
"zero",
"range",
"shot",
"shoot",
"hop",
"rage",
"fang",
"age"
};
var target = "zero_range_shot";
var top5mostRelated = list
.OrderByDescending(str => str.ToUpper().DistanceFrom(target.ToUpper()))
.Take(5).ToList();
foreach (var str in top5mostRelated) Console.WriteLine(str);
}
}
,输出为: 范围 零 射击 射击 芳
答案 2 :(得分:1)
我不知道这是问题的根源,但我首先要重构代码,以便textBox1.Text
只读一次:
string theText = textBox1.Text.ToUpper();
query = Files
.Where(file => file.Fileinfo.Name.ToUpper().Contains(theText))
.Take(7).ToList();
答案 3 :(得分:0)
也许零中的O实际上是数字0而不是字母O?
答案 4 :(得分:0)
您是否在调试器中确认了textbox1.Text属性?
对TextChanged
而言,KeyPress
可能比{{1}}更好?