2010-10-13 49 views
6

我有一个ObservableCollection,它包含一个Person对象。我在我的应用程序中有一个搜索功能,并希望在顶部显示最相关的结果。什么是最有效的方法呢?我目前的搜索方法只是调用contains方法:Linq按最接近的匹配搜索结果

var results = (from s in userList 
       where s.Name.Contains(query) 
       select s).ToList(); 

也能正常工作,但结果中出现内userList相同的顺序排列。如果我搜索Pete,那么它应该首先显示Pete,然后Peter然后Peter Smith等。 它不必太复杂,因为它只会处理几千(最大)的结果。我天真的做法是首先做s.Name == query,显示该项目(如果有的话),然后执行s.Name.Contains(query),删除匹配的项目并将其追加到先前的匹配结果。然而,这似乎有点到处,所以还有更好的方法吗?谢谢 (ps - 只有名称将用于搜索,并且我不能使用SQL方法)

回答

10

您可以制作一个提供名称和查询字符串的例程,并返回一个整数值。

一旦你的,只是通过ORDER BY返回:

int QueryOrder(string query, string name) 
{ 
    if (name == query) 
     return -1; 
    if (name.Contains(query)) 
     return 0; 

    return 1; 
} 

然后做:

var results = userList.OrderBy(s => QueryOrder(query, s.Name)); 

这种方法的好处是,以后,你可以扩展程序来提供更多细节,让您根据您收到的比赛的“优秀”进行排序。例如,“皮特” - >“彼得”可能比“皮特” - >“彼得史密斯”更好的匹配,所以你可以让你的逻辑为不同的选项返回不同的值...

如果你需要删除“非皮特”匹配,你也可以用Where子句排除。

+0

谢谢,我只是测试了这一点,它似乎工作完美。尼斯和简单:) – Brap 2010-10-13 16:45:58

7

你需要的是某种类似的评分函数。然后,你可以这样做:

from s in userList 
let score = Score(s, query) 
where score > 80 
orderby score descending 
select s; 

现在是不是从你的榜样正是清晰(这是假设打分函数给出0-100,其中100是一个完美的匹配之间的值。)得分功能应该是什么 - 这是你的工作:)

+0

感谢您的帮助。我打算采用汉明距离方法,但对于这个问题可能有点矫枉过正,效率低下。 – Brap 2010-10-13 16:46:56

0
var results = (from s in userList 
       where s.Name.Contains(query) 
       orderBy s.Length 
       select s).ToList();