2015-10-26 10 views
6

私は次のコードを使って、ユーザーが指定する検索フレーズに基づいて「説明」を探しています。キーを重要なフレーズと考えて、そのフレーズを見つけるためにどこに行くかについての説明として考えてください。
店舗のロケータと考えることができます(私が考えることができる最高のアナロジー)。 「ターゲット」(キー)を検索すると、数多くの都市(値)が得られます。また、同じ名前を持つ都市もあります。したがって、同じ都市に複数のターゲットが存在する可能性があります。
Dictionaryは明らかに機能しません。店名が重複しているか、都市名が重複している可能性があるからです。私の実際の状況に私をもたらします:Linqキー(または部分キー)で検索値を検索する代わりに

基本的に、私はList<KeyValuePair<string, string>>から始まり、両方向で重複を許してから、それをLookup<string, string>に変換しました。

List<KeyValuePair<string, string>> kvpList = new List<KeyValuePair<string, string>>(); 
Lookup<string, string> collection; 

kvpList.Add(new KeyValuePair<string, string>("K1", "R1")); 
kvpList.Add(new KeyValuePair<string, string>("K1", "R1")); 
kvpList.Add(new KeyValuePair<string, string>("K1", "R2")); 
kvpList.Add(new KeyValuePair<string, string>("K2", "R1")); 
kvpList.Add(new KeyValuePair<string, string>("K2", "R2")); 
kvpList.Add(new KeyValuePair<string, string>("K2", "R3")); 
kvpList.Add(new KeyValuePair<string, string>("K2", "R1")); 

collection = (Lookup<string,string>)kvpList.ToLookup(k => k.Key, k => k.Value); 

上記は、単に偽のテスト情報であるが、非常にLINQのフレンドリーであるように思われる、特に以来Lookupからの結果を得るためにクリーンな方法がなければならないような気がします。残念なことに、私はLinqにはあまりよく慣れていません。Linq自体の構文は、とても初心者には向いていないようです。私はこのコードで結果(単なるテスト目的のためにハードコード化された検索語)を取得:

string searchTerm = "K2"; 
List<string> uniqueResults = new List<string>(); 

foreach (var item in collection) 
{ 
    if (item.Key.Contains(searchTerm)) 
    { 
     foreach (var value in item) 
     { 
      if (!uniqueResults.Contains(value)) 
      { 
       uniqueResults.Add(value); 
       Console.WriteLine("Added: " + value); 
      } 
      else 
      { 
       Console.WriteLine("Skipped duplicate: " + value); 
      } 
     } 
    } 
} 

私は上記のコードの問題を持っていないが、私の質問です:LINQのを使用する方法はあります私が達成しようとしていることを達成するために?私が持っているような気がするのは、これができる最善の方法ではない...
部分searchTermは、キー(それゆえ含まれている)で結果が見つかるようにする必要があります。既存の回答は私の特定の質問にはあまり答えられませんでした。部分的なキー検索で値を取得するのに役立つものは見つかりませんでした。

+0

ルックアップは辞書と似ていますが、部分文字列検索はありません。文字列の一部を扱うことができない 'GetHashCode'を使うので、部分文字列検索が必要な場合は集合ベースのアプローチを使用できません(どのようにしてすべての部分文字列に対して単一の値を返すことができますか?)。 –

+0

あなたの質問ではるかに目立つ "部分的な検索キーワードの検索結果をキー内で見つけることができる必要があります"ということを提案し、タイトルを変更して最初の数段落の一部にすることをお勧めします。それは私が思うように質問を形作ります。 – 31eee384

+0

ありがとう@ 31eee384、変更を加えました。 –

答えて

6

はあなたのコード

var uniqueResults = collection 
     .Where(item => item.Key.Contains(searchTerm)) // filter the collection 
     .SelectMany(x => x)       // flatten results 
     .Distinct()         // remove duplicates 
     .ToList(); 

あなたもそうではありませんLookupが必要です。あなたはkvpListと同じ結果を得ることができます。

var uniqueResults = kvpList 
     .Where(item => item.Key.Contains(searchTerm)) // filter the collection 
     .Select(item => item.Value)     // get the Values from KeyValuePairs 
     .Distinct()         // remove duplicates 
     .ToList(); 

LINQのソリューションは、実際には必須のものより理解する方がはるかに簡単です。アルゴリズムを英語で説明してください:kvpListから、キーに検索語が含まれている場合は別の値を選択してください。それはほぼ正確に2番目のLINQコードです。

+3

ルックアップはここでは役に立たない。 OPは 'kvpList'だけを使うべきです(' collection'を 'kvpList'に置き換えてください)。 –

+0

@TimSchmelterあなたが正しいです。ルックアップ付きのバージョンよりも理解しやすいです。私は両方のバージョンを答えに含めました。 –

+0

ありがとう@JakubLortz!これにより、LINQの方法を理解するのがずっと簡単になります。コンテキストを理解することは間違いありません。 –

1

あなたはあなたのための重複を排除することになる、LINQとHashSet<string>を使用することができます。

ToHashSetはあなたが簡単に作成できるカスタム拡張メソッドである
var uniqueResults = collection.Where(item => item.Contains(searchTerm)) 
           .SelectMany(x => x) 
           .ToHashSet(); 

:LINQに翻訳

public static class EnumerableExtensions 
{ 
    public static HashSet<T> ToHashSet(this IEnumerable<T> enumerable) 
    { 
     return new HashSet<T>(enumerable); 
    } 
} 
+0

あなたは平坦化の1つのレベルがありません。問題の 'uniqueResults'には値が含まれています.HashSetの列挙型ではありません。 – CoderDennis

+0

@CoderDennisありがとう、私はそれを逃した。 –

+1

Jakubの答えほど簡単ではありませんが、まだとても涼しいです。私の+1。 –

関連する問題