2012-07-09 103 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);