2010-10-13 99 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();