2016-08-03 4 views
3

ユーザ入力は、私は以下の製品最も具体的な一致する項目

public class Product 
{ 
    public string Name {get;set;} 
    public string Id {get;set;} 
} 

でのソースリストを持っている

var items = new List<string> {'BY1 2PX', 'BY12', 'BY1', 'BY'}; 

以下のように分割し、リストに格納される、「BY1 2PX」のようになります見つけますサンプルの製品リスト注文に必要なものはありません。それはどのような順序でもかまいません。

var products = new List<Product>{ 
    new Product("1", "BY1 2PX"), 
    new Product("2", "BY12"), 
    new Product("3", "BY1"), 
    new Product("4", "BY"), 
    new Product("5", "AA2 B2X"), 
    //...etc 
} 

私の出力は、最も特定の一致があるため、1をフェッチする必要があります。 Id = 1がそこになければ、それはId = 2のようにフェッチされているはずです...誰でもlinqクエリを書いてくれたら助かりますか?私は以下のようなものを試しましたが、これは大丈夫ですか?

+1

商品リストは、特定の一致がより少なくなる前に「最も具体的な」一致が発生した順番で並べ替えられますか?そうでない場合は、どのようにマッチの優先順位を定義しますか? –

+0

'List 'がなぜ必要なのですか? 'Dictionary 'を使うと単純化しませんか?辞書の検索ははるかに高速です。 – Fabjan

+0

'string.Equals'を使用しているので、「最も具体的」は少し不明です。これにより、最初の* exact *マッチが見つかります。 – Groo

答えて

1

ベストマッチングする製品を選択する場合は、文字列リストではなく製品から選択する必要があります。

Product bestProduct = products 
    .Select(p => new { 
     Product = p, 
     Index = items.FindIndex(s => String.Equals(p.Name, s, StringComparison.OrdinalIgnoreCase)) 
    }) 
    .Where(x => x.Index != -1) 
    .OrderBy(x => x.Index) // ensures the best-match logic 
    .Select(x => x.Product) 
    .FirstOrDefault(); 

Whereは全く一致するものがない場合、あなたは、任意の製品を取得することはできませんことを保証します:あなたはList.FindIndexを使用して、次のLINQのアプローチを使用することができます。


更新

、より効率的なソリューションは、このクエリです:

Product bestProduct = items 
    .Select(item => products.FirstOrDefault(p => String.Equals(p.Name, item, StringComparison.OrdinalIgnoreCase))) 
    .FirstOrDefault(p != null); // ensures the best-match logic 
+0

これは、「最も具体的な」要素を得るためのOPのニーズにどのように対処しますか?つまり、完全一致が見つからない場合は、次に一致するものを選択します。 –

+0

@roryap、IMO、最も具体的なインデックス*として 'items'リスト内の* seach criteria *は最小であり、そのインデックスによるリストはそれを解決します。 –

+0

@AdilMammadov - OPは、そのリストがそのような順序ではないことを明らかにしました... –

0

あなたが主に使用されているLevenshtein's distance algorythmと呼ばれる特定のalgorythmを、使用して単語の類似点を見つけることを試みることあなたはほとんどの検索サイトで「単語」を意味しましたか?

このソリューション

はここで見つけることができます:あなたは距離差を見つけたら https://stackoverflow.com/a/9453762/1372750

は、あなたが検索さ1「のような」よりは、ある単語やフレーズを測定することができます。

var productsDict = products.ToLookup(p => p.Name, p => p); 

var key = items.FirstOrDefault(i => productsDict.Contains(i)); 

Product result = key != null ? productsDict[key] : null; 
2

さて、あなたはその高速な検索で辞書を使用することができます商品ごとに「最も具体的」(最長)の一致があり、どちらの商品の注文にもかかわらず、最長の商品が返されます。

var result = products 
      .Select(p => new 
       { 
        Product = p, 
        MostSpecific = items.Where(item => p.Name.Contains(item)) 
             .OrderByDescending(match => match.Length 
             .FirstOrDefault() 
       }) 
      .Where(x => x.MostSpecific != null) 
      .OrderByDescending(x => x.MostSpecific.Length) 
      .Select(x => x.Product) 
      .FirstOrDefault(); 
0

これは見つける:あなたは、ルックアップを使用することができ、同じ名前を持つ複数の要素を持っている場合は、

var productsDict = products.ToDictionary(p => p.Name, p => p); 

var key = items.FirstOrDefault(i => productsDict.ContainsKey(i)); 

Product result = key != null ? productsDict[key] : null; 

またはTIMが示唆したように:

関連する問題