2015-07-13 35 views
2

我有一個列表,其中包含供應商的名稱。說如何使用LINQ執行單詞搜索?

SuppId Supplier Name 
---------------------------------- 
1  Aardema & Whitelaw 
2  Aafedt Forde Gray 
3  Whitelaw & Sears-Ewald 

使用下面的LINQ查詢

supplierListQuery = supplierListQuery.Where(x => x.SupplierName.Contains(SearchKey)); 

我可以在下列情況下返回正確的記錄,

1)如果我使用的搜索字符串作爲「懷特洛&西爾斯·埃瓦爾德」它將返回第3條記錄。

2)如果我使用「懷特洛」或「西爾斯·埃瓦爾德」它將返回3記錄。

但是我如何返回第3條記錄,如果我給搜索字符串爲「Whitelaw Sears-Ewald」。它總是返回0個記錄。

我可以使用ALL來獲得這個結果,但我不知道如何使用它來滿足這個特殊的需求。

+1

構建智能搜索引擎是一件不平凡的事情。有很多*語言解析和邏輯進入它,遠遠超過一個單一的LINQ語句。 – David

+2

您需要的是模糊搜索哪些LINQ不能開箱即用。閱讀這個http:// stackoverflow。COM /問題/ 13162830 /寬容的模糊搜索與 - LINQ – timothyclifford

+0

是您的要求,在這裏治療「懷特洛」和「西爾斯·埃瓦爾德」作爲單獨的搜索詞,返回包含至少一個搜索項的任何記錄? – Max

回答

1

謝謝大家對你的快速反應。但是,對於這個問題,蒂莫西克利福德的提示表明了這一點。就像他說我改變了我對此的回答

string[] filters = SearchKey.ToLower().Split(new[] { ' ' }); 
objSuppliersList = (from x in objSuppliersList 
        where filters.All(f => x.SupplierName.ToLower().Contains(f)) 
        select x).ToList(); 

現在它返回所有我的選擇條件的結果。

+0

嘗試搜索「Aafedtzzzzz」或「WhitelawSears-Ewald」並查看是否得到任何結果;) – Fabjan

+0

@ Fabjan是的你是對的,但是當我遵循Juann Strauss的方法時,當我使用selaw key作爲「Whitelaw Sears-Ewald PLLC」時,我無法找到結果。你的方法的問題是,我有超過10000個供應商記錄在我的分貝,每次用戶點擊serach按鈕我需要執行搜索這些記錄。我也需要考慮過濾器查詢。所以我對整體表現感到緊張。 –

+0

通過使用timothyclifford的方法,現在我可以處理我的基本搜索查詢。所以我暫時用這種方法。感謝您通知我。 :) –

0

您需要使用某種形式的字符串比較器來創建自己的簡單的搜索引擎,然後你可以找到最有可能被包含在結果字符串:

public static class SearchEngine 
{ 

    public static double CompareStrings(string val1, string val2) 
    { 
     if ((val1.Length == 0) || (val2.Length == 0)) return 0; 
     if (val1 == val2) return 100; 

     double maxLength = Math.Max(val1.Length, val2.Length); 
     double minLength = Math.Min(val1.Length, val2.Length); 
     int charIndex = 0; 
     for (int i = 0; i < minLength; i++) { if (val1.Contains(val2[i])) charIndex++; } 

     return Math.Round(charIndex/maxLength * 100); 
    } 

    public static List<string> Search(this string[] values, string searchKey, double threshold) 
    { 
     List<string> result = new List<string>(); 
     for (int i = 0; i < values.Length; i++) if (CompareStrings(values[i], searchKey) > threshold) result.Add(values[i]); 
     return result; 
    } 
} 

使用示例:

string[] array = { "Aardema & Whitelaw", "Aafedt Forde Gray", "Whitelaw & Sears-Ewald" }; 

var result = array.Search("WhitelawSears-Ewald", 80); 
// Results that matches this string with 80% or more 

foreach (var item in result) 
{ 
    Console.WriteLine(item); 
} 

輸出:Whitelaw & Sears-Ewald

6

我通常在這種情況下做的話分成集合,然後執行以下操作:

var searchopts = SearchKey.Split(' ').ToList(); 
supplierListQuery = supplierListQuery 
    .Where(x => searchopts.Any(y=> x.SupplierName.Contains(y))); 
+0

似乎是合理的我,會有-1詳細說明嗎? – Max

+2

這太有用了。謝謝 –

+0

很高興我能幫到你。 –

-1

如果你想要一個簡單的(不是很方便)解決方案,

var result = supplierListQuery 
         .Select(x => normalize(x.SupplierName)) 
         .Where(x => x.Contains(normalize(SearchKey))); 

string normalize(string inputStr) 
{ 
    string retVal = inputStr.Replace("&", ""); 
    while (retVal.IndexOf(" ") >= 0) 
    { 
     retVal = retVal.Replace(" ", " "); 
    } 
    return retVal; 
} 
1

這個工作對我來說:

IEnumerable<string> keyWords = SearchKey.Split(''); 

supplierListQuery = supplierListQuery 
     .AsParallel() 
     .Where 
     (
     x => keyWords.All 
     (
       keyword => x.SupplierName.ContainsIgnoreCase(keyword) 
     ) 
    ); 
0

因爲「懷特洛」同時出現在你會得到兩個記錄。否則,沒有動態的方式來確定你只想要最後一個。如果你知道你只有這3個,然後附加.Last()來獲得最終的記錄。

 
supplierListQuery = supplierListQuery.Where(x => x.SupplierName.Contains(SearchKey.Split(' ')[0])); 
+0

您選擇的答案僅適用,因爲Whitelaw首先在您的字符串中。做一個真正的搜索,你會希望它找到匹配Whitelaw的所有記錄,然後從那裏過濾找到你想要的。您可以像這樣輕鬆完成:supplierListQuery = supplierListQuery..Where(x => x.SupplierName.StartsWith(SearchKey.Split()[0]));獲取與查詢中第一個單詞相匹配的記錄。 –