【问题标题】:Sort by Count Occurrences of a Word in list rows linq按列表行中某个单词的出现次数排序
【发布时间】:2017-12-19 03:03:52
【问题描述】:

如何根据每行 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 

【问题讨论】:

  • 我对优先搜索词的编辑是否解决了这个问题?

标签: c# linq


【解决方案1】:

在这一行之后:

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();
}

【讨论】:

  • 你的技巧有效....但是你像 Console.WriteLine(item.Title); 一样循环打印但我想返回一个列表......因为我需要将列表绑定到网格。尝试返回一个列表而不是在循环中打印。谢谢
  • 在 foreach 循环之外声明一个列表: var myList = new List();代替 Console.WriteLine,您可以执行 myList.Add(item);还是……我错过了什么?
【解决方案2】:

使用 WordCount 作为字符串的扩展方法,然后可以使用简单的 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;
        }
    }

【讨论】:

  • 我这样做了,但在 LINQ 垫中不起作用。这是代码 var result = from searchResult in list let key_string = to_search.FirstOrDefault(ts => searchResult.Title.ToLower().Contains(ts.ToLower())) 通过 key_string 将 searchResult 分组到 Group orderby Group.Count()降序选择组; //result.ToList().Dump(); result.OrderByDescending(sR => sR.Title.WordCount("GEO")).ToList().Dump();
  • @Thomas 我不确定你想用你发布的那个 LINQ pad 代码来完成什么,你是什么意思它不起作用? (LINQ pad 是否有特定错误?)我一直在使用一个简单的控制台应用程序来测试我编写的代码
  • @Thomas 它不起作用,因为result 是一个分组列表,而您的最后一行需要一个SearchResult 类型的列表。
  • 好的,谢谢,但请告诉我为什么我需要反向搜索词,如 searchTerms.Reverse() ?有什么原因吗。请讨论
【解决方案3】:

这个怎么样:

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;

使用以下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;
}

我注意到的一个小问题是不包含匹配单词的标题将被组合在一起,因此可以将它们放在匹配单词的标题前面。

【讨论】:

    猜你喜欢
    • 2011-01-22
    • 1970-01-01
    • 2018-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-24
    • 1970-01-01
    相关资源
    最近更新 更多