2012-07-09 47 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; 
} 

一个小问题,我注意到的是不含匹配的单词的标题将被组合在一起,这样就可以让他们放在标题前面匹配的话。