2012-07-09 101 views
1

我已存儲的數據列表一樣排序列表

List<SearchResult> list = new List<SearchResult>(); 
SearchResult sr = new SearchResult(); 
sr.Description = "sample description"; 
list.Add(sr); 

想我的數據存儲在描述字段一樣

"JCB Excavator - ECU P/N: 728/35700" 
"Geo Prism 1995 - ABS #16213899" 
"Geo Prism 1995 - ABS #16213899" 
"Geo Prism 1995 - ABS #16213899" 
"Wie man BBA reman erreicht" 
"this test JCB" 
"Ersatz Airbags, Gurtstrammer und Auto Körper Teile" 

現在我想查詢列表與像地理JCB

我的搜索詞,如果你看那麼這個詞地理已經存儲了很多次在描述字段中。所以我想以這樣的方式對我的列表進行排序,使得搜索詞中的單詞最大限度地發現數據將首先出現。請幫助我這樣做。感謝

+1

HTTP://en.wikipedia。org/wiki/Tf%2Aidf – 2012-07-09 09:12:59

回答

1

你可以使用一個簡單的正則表達式,只是|結合您的搜索字詞的格局:

var re = new Regex("geo|JCB",RegexOptions.IgnoreCase); 

再算在你的描述匹配的數量:

Console.WriteLine(re.Matches(description).Count); // Outputs '5' in your example 

你可以通過以下順序排列清單:

searchResults.OrderByDescending(r => re.Matches(r).Count); 

現場示例:http://rextester.com/MMAT58077


編輯:根據您在評論鏈接新問題(希望你會更新這個問題的細節,讓重複的模具)你想訂購的結果,因此,最常見結果顯示在結果列表的前面。

要做到這一點,您可以先計算每個搜索短語的相關權重,然後使用它來排序結果。

第一步:通過計數的總次數的每個搜索詞出現在整個數據集的計算的加權:

var wordsToFind = "Geo JCB".Split(); 
// find number of times each search phrase is found 
var weights = wordsToFind.Select(w => new { 
     Word = w, 
     Weight = list.Where(x => x.Description.Contains(w)).Count() 
    }); 

對於此刻這一問題的數據這givves結果:

GEO: 3 
JCB: 2 

所以你想要所有的GEO結果第一,其次是JCB。我想一個好的將有第一個結果是最經常提到的GEO

步驟2:使用步驟1中計算的權重來排序搜索結果。

var values = list.Select(x => new { 
     SearchResult = x, 
     Words = x.Description.Split(' ') 
    }) 
    .Select(x => new { 
     SearchResult = x.SearchResult, 
     Weight = weights.Sum(w => x.Words.Contains(w.Word) ? w.Weight : 0) 
    }) 
    .OrderByDescending(x => x.Weight) 
    .Select(x => x.SearchResult); 

活生生的例子:http://rextester.com/SLH38676

+0

我再次在這裏發佈修改過的問題...請查找我的requiremnt。這裏的網址http://stackoverflow.com/questions/11393627/complex-sorting-list-by-occurrence-of-a-word-by-linq-c-sharp – Thomas 2012-07-09 11:05:43

+0

@Thomas - 你需要更新**這**問題與更新的信息,你的新問題將很快關閉作爲一個副本(當我投票結束時,它有5票中的4票) – Jamiec 2012-07-09 12:42:33

+0

@Thomas - 請參閱更新 – Jamiec 2012-07-09 13:08:59

1
List<SearchResult> list = new List<SearchResult>() 
{ 
    new SearchResult { Description = "JCB Excavator - ECU P/N: 728/35700" }, 
    new SearchResult { Description = "Geo Prism 1995 - ABS #16213899" }, 
    new SearchResult { Description = "Geo Prism 1995 - ABS #16213899" }, 
    new SearchResult { Description = "Geo Prism 1995 - ABS #16213899" }, 
    new SearchResult { Description = "Wie man BBA reman erreicht" }, 
    new SearchResult { Description = "this test JCB" }, 
    new SearchResult { Description = "Ersatz Airbags, Gurtstrammer und Auto Körper Teile" }    
    }; 

    var wordsToFind = "Geo JCB".Split(); 
    var values = list.Select(x => new { SearchResult = x, Count = x.Description.Split(' ') 
              .Where(c => wordsToFind .Contains(c)).Count() }) 
        .OrderByDescending(x => x.Count) 
        .Select(x => x.SearchResult); 
+0

這一行給出錯誤Count = x.Split('')錯誤信息msg是「WindowsFormsApplication1.SearchResult不包含'Split'的定義,也沒有接受類型'WindowsFormsApplication1.SearchResult'的第一個參數的擴展方法'Split'可能是發現(你是否錯過了使用指令或程序集「 – Thomas 2012-07-09 10:23:23

+0

使用x.Description.Split ..剛剛更新了答案。 – 2012-07-09 10:24:43

+0

沒有用,當我綁定我的datagrid像dataGridView2.DataSource = values.ToList();數據進來相同訂單.....沒有更改發現 – Thomas 2012-07-09 10:31:55

2

您可以使用string.SplitEnumerable.OrderByDescending與匿名類型:

List<SearchResult> list = new List<SearchResult>() { 
    new SearchResult(){Description="JCB Excavator - ECU P/N: 728/35700"}, 
    new SearchResult(){Description="Geo Prism 1995 - ABS #16213899"}, 
    new SearchResult(){Description="Geo Prism 1995 - ABS #16213899"}, 
    new SearchResult(){Description="Geo Prism 1995 - ABS #16213899"}, 
    new SearchResult(){Description="Wie man BBA reman erreicht"}, 
    new SearchResult(){Description="this test JCB"}, 
    new SearchResult(){Description="Ersatz Airbags, Gurtstrammer und Auto Körper Teile"}, 
}; 

string[] searchTerms = new[]{"geo", "jcb"}; 
var results = 
    list.Select(sr => new { Searchresult = sr, Words = sr.Description.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries) }) 
     .OrderByDescending(x => x.Words.Count(w => searchTerms.Contains(w.ToLower()))) 
     .Select(x => x.Searchresult); 
+0

沒有用,當我綁定我的datagrid像dataGridView2.DataSource = results.ToList();數據以相同的順序發生.....沒有發現變化。 – Thomas 2012-07-09 10:32:21

+0

@Thomas:展示你做了什麼。順便說一下,在您的示例數據中,有5個搜索結果有1個匹配詞,沒有多於1個,兩個匹配0個。也許這就是你認爲沒有區別的原因。 – 2012-07-09 10:38:36

+0

我的要求有點不同,第一次排序就像那些排在搜索項最長時間的地方排在第一位。結果GEO在5行中發現了3次。 JCB在行中發現兩次。所以所有的行都從GEO開始,然後是下一個JCB。再次排序將會像GEO發現最大時間的行將排在第一位。這裏GEO&JCB只在樣品中找到一次。如果可能,請根據我的要求更改我們的代碼。謝謝 – Thomas 2012-07-09 11:00:35

0
var results = db.Blogs.AsEnumerable() 
    .Select(sr => new 
    { 
     Searchresult = sr, 
     Words = Regex.Split(sr.Name, @"[^\S\r\n {1,}").Union(Regex.Split(sr.Name2, @"[^\S\r\n]{1,}")) 
    }) 
    .OrderByDescending(x => x.Words.Count(w => { 
     foreach (var item in searchTerms) 
     { 
      if(w.ToLower().Contains(item)) 
      { 
       return true; 
      } 
     } 
     return false; 
    })) 
    .Select(x => x.Searchresult);