2012-07-09 88 views
3

如何根據linq數據的每一行中出現的字來排序列表?我從這裏得到了一個正在給出正確輸出的人的答案。下面是代碼:按列表行中列出的字的出現次數linq

void Main() 
{ 
    List<SearchResult> list = new List<SearchResult>() { 
     new SearchResult(){ID=1,Title="Geo Prism GEO 1995 GEO* - ABS #16213899"}, 
     new SearchResult(){ID=2,Title="Excavator JCB - ECU P/N: 728/35700"}, 
     new SearchResult(){ID=3,Title="Geo Prism GEO 1995 - ABS #16213899"}, 
     new SearchResult(){ID=4,Title="JCB Excavator JCB- ECU P/N: 728/35700"}, 
     new SearchResult(){ID=5,Title="Geo Prism GEO,GEO 1995 - ABS #16213899 GEO"}, 
     new SearchResult(){ID=6,Title="dog"}, 
    }; 

    var to_search = new[] { "Geo", "JCB" }; 

    var result = from searchResult in list 
     let key_string = to_search.FirstOrDefault(ts => searchResult.Title.ToLower().Contains(ts.ToLower())) 
     group searchResult by key_string into Group 
     orderby Group.Count() descending 
     select Group; 
     result.ToList().Dump(); 



} 
// Define other methods and classes here 
public class SearchResult 
{ 
    public int ID { get; set; } 
    public string Title { get; set; } 
} 

我越來越喜歡

ID Title 
-- ------ 
1 Geo Prism GEO 1995 GEO* - ABS #16213899 
3 Geo Prism GEO 1995 - ABS #16213899 
5 Geo Prism GEO,GEO 1995 - ABS #16213899 GEO 
2 Excavator JCB - ECU P/N: 728/35700 
4 JCB Excavator JCB- ECU P/N: 728/35700 
6 dog 

輸出上面的輸出就可以了。所有具有ord GEO的行都首先出現,因爲它在大多數行中發現最大時間意味着GEO字在3行中找到,而JCB在兩行中找到,因此接下來是JCB相關行。

我需要在整個數據上獲得上述輸出後再進行排序。那就是GEO行首先出現在哪個行的GEO字的最大時間。所以,我的輸出看起來象下面這樣:

ID Title 
-- ------ 
5 Geo Prism GEO,GEO 1995 - ABS #16213899 GEO 
1 Geo Prism GEO 1995 GEO* - ABS #16213899 
3 Geo Prism GEO 1995 - ABS #16213899 
4 JCB Excavator JCB- ECU P/N: 728/35700 
2 Excavator JCB - ECU P/N: 728/35700 
6 dog 

我發現了一個LINQ查詢,其對一個詞的出現在字符串:

string text = @"Historically, the world of data and data the world of objects data" ; 
string searchTerm = "data"; 
//Convert the string into an array of words 
string[] source = text.Split(new char[] { '.', '?', '!', ' ', ';', ':', ',' }, StringSplitOptions.RemoveEmptyEntries); 
var matchQuery = from word in source 
      where word.ToLowerInvariant() == searchTerm.ToLowerInvariant() 
      select word; 
int wordCount = matchQuery.Count(); 

我從this url

得到它我怎麼能使用上面的代碼來排序我的標題?如何使用第二個排序計數在標題字段中單詞的出現,結果我的輸出看起來像:

ID Title 
-- ------ 
5 Geo Prism GEO,GEO 1995 - ABS #16213899 GEO 
1 Geo Prism GEO 1995 GEO* - ABS #16213899 
3 Geo Prism GEO 1995 - ABS #16213899 
4 JCB Excavator JCB- ECU P/N: 728/35700 
2 Excavator JCB - ECU P/N: 728/35700 
6 dog 
+0

我的優先搜索條件編輯解決了嗎? – James 2012-07-09 20:29:26

回答

0

這一行後:

var result = from searchResult in list 
     let key_string = to_search.FirstOrDefault(ts => searchResult.Title.ToLower().Contains(ts.ToLower())) 
     group searchResult by key_string into Group 
     orderby Group.Count() descending 
     select Group; 

你想是這樣的:

foreach (var group in result) { 
     foreach (var item in group.OrderByDescending(theItem => WordCount(theItem.Title, group.Key))) { 
      Console.WriteLine(item.Title); 
     } 
} 

與添加的方法是這樣的:

public static int WordCount(string haystack, string needle) { 
    if (needle == null) { 
     return 0; 
    } 
    string[] source = haystack.Split(new char[] { '.', '?', '!', ' ', ';', ':', ',' }, StringSplitOptions.RemoveEmptyEntries); 
    var matchQuery = from word in source 
         where word.ToLowerInvariant() == needle.ToLowerInvariant() 
         select word; 
    return matchQuery.Count(); 
} 
+0

你的技巧工程....但你打印在循環像Console.WriteLine(item.Title); 但我想返回一個列表.... bcoz我需要將列表綁定到網格。嘗試返回一個列表,而不是在foreach循環外打印。謝謝 – Thomas 2012-07-10 08:40:37

+0

聲明一個列表:var myList = new List ();而不是Console.WriteLine,你可以做myList.Add(item);或者...我錯過了什麼? – aquinas 2012-07-10 13:40:54

1

用字計數作爲擴展方法的字符串,然後你可以使用簡單的Lambda表達式:

list.OrderByDescending(sR => sR.Title.WordCount(to_search)) 

如果您想忽略沒有任何搜索條件的所有結果,則可以使用Where子句。即

IEnumerable<SearchResult> results = list 
       .Where(sR => sR.Title.WordCount(searchTerms) > 0) 
       .OrderByDescending(sR => sR.Title.WordCount(searchTerms)); 

編輯 如果搜索而言,具有優先給他們,你可以做多個排序上的每個項目一樣由最低優先級元素,那麼接下來左右(第一排序,直到最後的排序是具有最高優先級的項目):

string[] searchTerms = new string[]{ "GEO","JCB" }; 
IEnumerable<SearchResult> results = list; 
foreach(string s in searchTerms.Reverse()) { 
    results = results 
     .OrderByDescending(sR => sR.Title.WordCount(s)); 
} 

擴展方法:

static class StringExtension{ 
     public static int WordCount(this String text, string searchTerm) 
     { 
      string[] source = text.Split(new char[] { '.', '?', '!', ' ', ';', ':', ',' }, StringSplitOptions.RemoveEmptyEntries); 
      var matchQuery = from word in source 
          where word.ToLowerInvariant() == searchTerm.ToLowerInvariant() 
          select word; 
      int wordCount = matchQuery.Count(); 
      return wordCount; 
     } 
     public static int WordCount(this String text, IEnumerable<string> searchTerms) { 
      int wordCount = 0; 
      foreach(string searchTerm in searchTerms) { 
       wordCount += text.WordCount(searchTerm); 
      } 
      return wordCount; 
     } 
    } 
+0

我做到了這一點,但在LINQ鍵盤中無法使用。這裏是代碼VAR結果=從信息搜索結果列表 讓KEY_STRING = to_search.FirstOrDefault(TS => searchResult.Title.ToLower()。包含(ts.ToLower())) \t \t \t組由KEY_STRING成 組信息搜索結果\t \t \t orderby Group.Count()降 \t \t \t select Group; \t \t \t //result.ToList()。Dump(); \t \t \t result.OrderByDescending(sR => sR.Title.WordCount(「GEO」))。ToList()。Dump(); – Thomas 2012-07-09 20:03:35

+0

@Thomas我不知道你用你發佈的LINQ pad代碼來完成什麼,你是什麼意思,它不工作? (是否有從LINQ墊特定的錯誤?)我一直在使用一個簡單的控制檯應用程序來測試我寫的代碼 – James 2012-07-09 20:08:45

+0

@Thomas它不起作用,因爲'result'是一個分組列表,而最後一行是期待一個「SearchResult」類型的列表。 – 2012-07-09 20:31:35

1

如何:

IEnumerable<SearchResult> result = 
    from searchResult in list 
    let key_string = to_search.FirstOrDefault(ts => searchResult.Title.ToLower().Contains(ts.ToLower())) 
    group searchResult by key_string into Group 
    orderby Group.Count() descending 
    from item in Group.OrderByDescending(theItem => WordCount(theItem.Title, Group.Key)) 
    select item; 

使用fol降脂WordCount方法:

public static int WordCount(String text, string searchTerm) 
{ 
    string[] source = text.Split(new char[] { '.', '?', '!', ' ', ';', ':', ',' }, StringSplitOptions.RemoveEmptyEntries); 
    var matchQuery = from word in source 
        where word.ToLowerInvariant() == searchTerm.ToLowerInvariant() 
        select word; 
    int wordCount = matchQuery.Count(); 
    return wordCount; 
} 

一個小問題,我注意到的是不含匹配的單詞的標題將被組合在一起,這樣就可以讓他們放在標題前面匹配的話。