3

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が2行で検出されたため、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();

このURLから取得しました

上記のコードを使用してタイトルを並べ替えるにはどうすればよいですか?タイトルフィールドでの単語の出現をカウントするために2番目の並べ替えを使用すると、出力は次のようになります。

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 
4

3 に答える 3

1

文字列の拡張メソッドとして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;
        }
    }
于 2012-07-09T19:57:04.263 に答える
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();
}
于 2012-07-09T19:58:47.483 に答える
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;

次の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;
}

私が気付いた小さな問題の1つは、一致する単語を含まないタイトルがグループ化されるため、一致する単語を含むタイトルの前に配置される可能性があることです。

于 2012-07-10T13:58:31.137 に答える