我的新列表(file.txt)中有几句话。例如:
等
我想在我的listBox中只显示包含在搜索框中输入的任何单词的句子。例如:当我输入" disney七个小矮人"时,它应该显示" Walt Disney支付了“白雪公主”和“七个小矮人”的动画师5美元,因为任何插曲都会成为电影的最终版本。"在列表的顶部。它不应该显示"电影十六蜡烛中的蛋糕由纸板制成。",因为这句话不包含任何输入的单词。简而言之:在顶部应该显示具有最多匹配单词的结果。
public static IEnumerable<string> SplitSearchWords(string str)
{
int charIndex = 0;
int wordStart = 0;
while (charIndex < str.Length)
{
wordStart = charIndex;
if (char.IsLetterOrDigit(str[charIndex]))
{
while (charIndex < str.Length && char.IsLetterOrDigit(str[charIndex])) charIndex++;
yield return str.Substring(wordStart, charIndex-wordStart);
}
else
{
while (charIndex < str.Length && !char.IsLetterOrDigit(str[charIndex])) charIndex++;
}
}
}
public static int CalculateSearchRelevance(string searchItem, IEnumerable<string> searchWords)
{
var searchItemWords = SplitSearchWords(searchItem);
return searchWords.Intersect(searchItemWords, StringComparer.OrdinalIgnoreCase).Count();
}
var myFile = File.ReadAllLines("file.txt");
var myList = new List<string>(myFile);
var query = textBox1.Text;
var items = myList;
var searchWords = SplitSearchWords(query).Distinct(StringComparer.OrdinalIgnoreCase).ToList();
var sortedItems = items.OrderByDescending(s => CalculateSearchRelevance(s, searchWords)).ToList();
答案 0 :(得分:0)
您可以使用String.Contains()方法并构建自定义函数来确定匹配百分比
答案 1 :(得分:0)
您需要在排序前检查是否有任何匹配的字词:
var searchWords = query.Split(null).Distinct(StringComparer.OrdinalIgnoreCase).ToList();
var matchingItems = items.Where(s => CalculateSearchRelevance(s, searchWords) > 0);
var sortedItems = matchingItems.OrderByDescending(s => CalculateSearchRelevance(s, searchWords)).ToList();
因为你不想展示“电影中的蛋糕十六个蜡烛是用纸板制成的。”
要显示最高匹配数,您需要某种状态,例如使用Dictionary
并保存所有匹配以进行进一步处理,或使用某些类来存储这些内容。
或强>
重新计算sortedItems
或
使用LINQ的Select并创建像ZiggZagg这样的匿名类型的答案,它更加优雅;)
编辑:在评论中解决您的问题
Intersect
将IEqualityComparer
作为其中一个参数。字符串的IEqualityComparer的默认实现使用Equals
,因此一种解决方案是编写自己的IEqualityComparer
实现,使用Contains
并根据它确定它是否相等。
class MyComparer : IEqualityComparer<string>
{
public bool Equals(string x, string y)
{
return x.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0;
}
public int GetHashCode(string obj)
{
return 0;
}
}
public static int CalculateSearchRelevance(string searchItem, IEnumerable<string> searchWords)
{
var searchItemWords = searchItem.Split(null).ToList();
return searchWords.Intersect(searchItemWords, new MyComparer()).Count();
}
其他方式是重写CalculateSearchRelevance,如下所示:
public static int CalculateSearchRelevance(string searchItem, IEnumerable<string> searchWords)
{
var searchItemWords = searchItem.Split(null);
return searchItemWords.Where(w => searchWords.Any(searchWord => w.IndexOf(searchWord, StringComparison.OrdinalIgnoreCase) >= 0)).Count();
}
通过上述实施,“迪斯尼”或“迪士尼”将与“迪士尼”和“迪士尼乐园”相匹配。我使用IndexOf而不是Contains来执行不区分大小写的操作。
请注意,如果您想要更高级的搜索引擎可能性,您可能需要查看基于Lucene构建的Lucene或Elasticsearch。你可以获得开箱即用的搜索引擎的所有功能:)许多巨头都会使用它。
答案 2 :(得分:0)
问题在于,即使它们不相关,您也始终包含所有结果。您只能通过检查相关性是否为&gt;来过滤项目以包含至少一个匹配项。 0
var sortedItems = items
.Select(s => new {Text = s, Relevance = CalculateSearchRelevance(s, searchWords)})
.Where(textWithRelevance => textWithRelevance.Relevance > 0)
.OrderByDescending(textWithRelevance => textWithRelevance.Relevance)
.ToList();
foreach (var sortedTextWithRelevance in sortedItems)
{
Console.WriteLine($"Relevance: {sortedTextWithRelevance.Relevance}, Text: {sortedTextWithRelevance.Text} ");
}