2009-08-11 15 views
3

私はすべての名前プロパティを持つベンダのC#にリストを持っています。私はユーザーが名前を検索してそのリストをフィルタリングできるようにしたい。フィルタ文字列は、部分一致または完全一致にすることができます。ただし、結果リストに完全一致が含まれている場合は、リスト内の位置が0で、その後の部分一致がすべて含まれている必要があります。リストの最初の特定の要素を持つリストのサブセットを選択

linqとlambdaを使ってサブリストを取得するのはかなり簡単ですが、正確に一致するものがあればそれを追加してから、残りの部分を追加するというハックに頼らざるを得ません正確なものそれは優しくないと感じます。簡単な方法がありますか?私の現在のコード(それはコンパイルできませんので、メモリから実行):Levenshtein距離を計算StringComparerの開発について

List<Vendor> temp = vendors.Where(v => v.Name.ToUpper().Contains(vendorNameSearch)).ToList(); 
Vendor exactMatch = vendors.Single(v => v.Name.ToUpper().Equals(vendorNameSearch)); 

if(null == exactMatch){return temp;} 
else 
{ 
    List<Vendor> temp1 = new List<Vendor>(); 
    temp1.Add(exactMatch); 
    temp1.AddRange(temp.Remove(exactMatch)); 
    return temp1; 
} 

答えて

3

方法 - これはゼロであるべき完全一致のために - と、この中で結果を注文昇順。このようにして、最初に完全一致を得て残りの検索結果を検索文字列に類似性(少なくとも1つの尺度)で並べ替えます。

var list = vendors.Where(v => v.Name.ToUpper().Contains(vendorNameSearch)) 
        .OrderBy(v => ComputeLevenshtein(v.Name.ToUpper(), 
                vendorNameSearch)); 

それとも、完全一致がint.MinValueであることと、他のすべての値は、()のCompareToの結果であることで物事を注文比較子を作ることができます。これにより、正確な一致が最初に表示されます。

1

私は、文字列の長さの絶対差順

List<String> strings = new List<String> {"Cat","Dog","Pear","Apple","Catalog"}; 

var results = (from st in strings 
    where st == "Cat" 
    select new {Priority = 1,st}).Union(

    from st in strings 
    where st.Contains("Cat") 
    select new {Priority = 2, st}).OrderBy(x => x.Priority).Select(x=> x.st).Distinct(); 
1

、これはですが、ここでは別のオプションがどのように効率的な見当がつかない。完全一致は、同じ長さを有する一つだけとなり、他は全て0より大きくなりながら(絶対差分= 0):

var list = vendors.Where(v => v.Name.ToUpper().Contains(vendorNameSearch)) 
        .OrderBy(v => Math.Abs(v.Name.ToUpper().Length - vendorNameSearch.Length))); 

それ以外の任意の順序になるだろうが、それは満たしますあなたの主な目標

もちろん、元のコードのような2段階の解決策には問題はありません。

3

まず、私はtvanfossonの答えのアプローチが使い勝手の観点から好きです。

そうでなければ、複合ソートを使用して、ご希望の動作を実現することができます:完全一致比較のブール結果によって

vendors.Where(v => v.Name.ToUpper().Contains(vendorNameSearch)) 
     .OrderBy(v => !string.Equals(v.Name, vendorNameSearch)) 
     .ThenBy(v => v.Name) 
     .ToList(); 

注文は、完全一致が最初にリストされていることを確認します。ブール値がソートされる方法のため、完全一致のベンダーはfalseの値を持つ必要があります。また、文字列の等価を反転するのではなく、OrderByDescendingを使用してこれを達成することもできます。

関連する問題