2009-11-12 59 views
1
 query = Files 
      .Where(file => file.Fileinfo.Name.ToUpper().Contains(textBox1.Text.ToUpper())) 
      .Take(7).ToList(); 

我讨厌问这个问题,但我根本没有任何进展!这看起来应该是一件小事,但我没有任何运气。c#“like/contains”通过列表搜索

上述查询需要通过文件名列表进行搜索。它会将搜索结果返回到排名前7位的相关结果列表中。该事件发生在“KeyPress”。

虽然,这是非常不庄重的,也有一些相当奇怪的结果。

例如:如果我的列表中的项目有一个名称:“ZeroWidthSplit” 如果我的文本框包含“Z”,它可以工作。如果它包含ZE它可以工作。如果它包含“ZER”它仍然显示。 如果我输入ZERO它会从搜索结果中消失!

所以我想我的问题是:你如何通过文件列表进行搜索,并使其返回前7个最相关的结果。

哦,如果只有4个相关的结果,那也没关系。该限制只是7.

又如:如果我写 “sum of” 作为搜索查询

F.X。它返回:

  1. 77 - 质数之和连续的素数五千 不同的方式
  2. 52总和低于 百万

如果我写 “sum of p” 返回:

  1. 77 - 质数五千之和 不同的方式

如果我写“sum of c”它没有返回值...

我可以给你更多的奇怪的例子。

+0

你还有7个结果回来? – manji 2009-11-12 10:39:30

+0

它确实返回结果,它们只是一点点不准确 - 然后是“零”错误,这只是一个例子。许多其他名字也是如此。 如果没有很多相关的结果,我的查询只会显示相关的结果。我只是将StringComparison枚举的最大值设置为7. – CasperT 2009-11-12 10:43:08

回答

1

在您的方案中如何定义“最相关的”? 如果你只是使用Contains,结果会错过很多“相关”的结果,这些结果与精确子串的形式不匹配。

你期待什么样的投入? 如果输入的只是一个字,那么这个算法可能会为你工作:

健身应作为 长度在 输入字符串中找到目标字符串的最长公共子 来计算,分目标字符串长度为 。例如,HPPLE 与APPLE 相比得分为0.8,因为在HPPLE中发现的APPLE 的最长子串是4个字母长, 是APPLE长度的.8。 此外,处罚由 0.1分数为每个外来字母输入串具有超过的 目标串的长度。例如。哈普勒 有得分.9相比苹果, 因为它是1个字母长, 否则有完整的子 苹果。请注意,这使得 候选词可能有 为负值。

当然还有很多其他更好的算法来计算距离。 如果输入可能包含多个单词,那么使用其他算法计算字符串之间的“距离”可能会更好。

和Umm ...你原来的查询没有结果进行排序,这样你就不会录取前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); 
    } 
} 

,输出是: 范围 零 拍摄 拍摄 方

1

我不知道这是问题的根源,但我会通过重构代码开始,这样textBox1.Text是只读一次:

string theText = textBox1.Text.ToUpper(); 

query = Files 
      .Where(file => file.Fileinfo.Name.ToUpper().Contains(theText)) 
      .Take(7).ToList(); 
4

错误听起来很奇怪,但作为Konamiman指出,虽然我不喜欢使用ToUpper或ToLower,但重构一点也不会伤害。我会这样做:

string theText = textBox1.Text; 

query = Files 
      .Where(file => file.Fileinfo.Name.IndexOf(theText, 
       StringComparison.OrdinalIgnoreCase) != -1) 
      .Take(7).ToList(); 
+0

+1。我总是忘记它存在。 – Konamiman 2009-11-12 10:58:46

+0

这很聪明。不幸的是,搜索结果是一样的 – CasperT 2009-11-12 11:36:56

0

也许O在零是实际的数字0而不是字母O?

+0

对不起,没有:)这只是一个例子。让我编辑我的OP,并向你展示另一个例子 – CasperT 2009-11-12 11:50:38

+0

这将是一个真正的大哦!如果这是问题的时刻。 :-) – Konamiman 2009-11-12 11:51:16

+0

增加了另一个例子。我有一吨 – CasperT 2009-11-12 11:53:33

0

你确认在textbox1.Text财产调试器?

也许TextChanged将是这方面比KeyPress更好的事件?