2016-05-02 4 views
1

パネルのリストをy値でソートしています。このように構造化されている理由の詳細については、my question from earlierを参照してください。短いストーリーでは、このリストは、位置0に最も高いパネル、位置1にそれより下のパネルなど、最後の位置の最後のパネルまで下がっています。私は高さ0に最も近いパネルのインデックスを見つける必要があるので、私はパネルがあるかを知るパネルのリストをバイナリ検索する方法

Panel p = panelList[someIndex]; 
int panelHeight = p.Top + p.Parent.Top - p.Parent.Margin.Top; 
//The above line guarantees that the first panel (index 0) has y-coordinate 0 when scrolled all the way up, 
//and becomes negative as the user scrolls down. 
//the second panel starts with a positive y-coordinate, but grows negative after the user scrolls past the top of that page 
//and so on... 

:私は、y座標、私のリンク質問から適応コード行を使用して、各パネルのをアクセスしていますが現在、またはそのページ上に非常に近いところにあります。したがって、私はスタックされているList.BinarySearch()メソッドを使用しようとしています。私はBinarySearchのプロパティを利用して、値がリスト内に存在する場合に値を返すことを望んでいます。そのようにすれば、高さ0のパネルを検索できます(見つからないと思っています)が、それに最も近い要素(y = 24またはy = -5のようなもの)を見つけて、それがパネルです現時点でレンダリングされています。

バイナリ検索を使用すると、<や>操作を定義したIComparerを指定できますので、私はこのクラス書いた:

class PanelLocationComparer : IComparer<Panel> 
{ 
    public int Compare(Panel x, Panel y) 
    { 
     //start by checking all the cases for invalid input 
     if  (x == null && y == null) { return 0; } 
     else if (x == null && y != null) { return -1; } 
     else if (x != null && y == null) { return 1; } 
     else//both values are defined, compare their y values 
     { 
      int xHeight = x.Top + x.Parent.Top - x.Parent.Margin.Top; 
      int yHeight = y.Top + y.Parent.Top - y.Parent.Margin.Top; 
      if (xHeight > yHeight) 
      { 
       return 1; 
      } 
      else if (xHeight < yHeight) 
      { 
       return -1; 
      } 
      else 
      { 
       return 0; 
      } 
     } 
    } 
} 

動作しない、と私は2つを比較するので、それがあることを今実現していますどのような値を探しているのか、実際にはy値= 0であるかどうかを気にする必要はありません。IComparerでこれを実装する方法はありますか、これを行う方法はありますか組み込みのBinarySearchを使用した検索のタイプ​​?

いつも私のPanelリストと同じ長さの新しいListを作成し、その中にy値をコピーしてから、このintリストを0で検索してみましたが、その作成、検索、破棄それらがスクロールするたびにリストはパフォーマンスを傷つけ、バイナリ検索のポイントを奪います。

私の質問はalso related to this oneですが、この状況ではアクセスできない組み込みの比較方法を最終的に使用するため、どのように調整するのか分かりませんでした。

答えて

1

残念ながら、組み込みのBinarySearchメソッドでは、このようなシナリオを処理できません。できるだけリストアイテムまたはリストアイテムから抽出できるものを検索するだけです。いくつかの項目は、偽の項目と適切な比較項目で使用できますが、ここでは該当しません。

バイナリ検索は非常に単純なアルゴリズムなので、次のようなときに自分自身を繰り返さないように、独自の拡張メソッドを作成して、簡単に作成することができます。

public static class Algorithms 
{ 
    public static int BinarySearch<TSource, TValue>(this IReadOnlyList<TSource> source, TValue value, Func<TSource, TValue> valueSelector, IComparer<TValue> valueComparer = null) 
    { 
     return source.BinarySearch(0, source.Count, value, valueSelector, valueComparer); 
    } 
    public static int BinarySearch<TSource, TValue>(this IReadOnlyList<TSource> source, int start, int count, TValue value, Func<TSource, TValue> valueSelector, IComparer<TValue> valueComparer = null) 
    { 
     if (valueComparer == null) valueComparer = Comparer<TValue>.Default; 
     int lo = start, hi = lo + count - 1; 
     while (lo <= hi) 
     { 
      int mid = lo + (hi - lo)/2; 
      int compare = valueComparer.Compare(value, valueSelector(source[mid])); 
      if (compare < 0) hi = mid - 1; 
      else if (compare > 0) lo = mid + 1; 
      else return mid; 
     } 
     return ~lo; // Same behavior as the built-in methods 
    } 
} 

、その後、単純に使用します。

int index = panelList.BinarySearch(0, p => p.Top + p.Parent.Top - p.Parent.Margin.Top); 
+0

を、私はそれに似た何かをやってしまいました。情報のおかげで! – Cody

関連する問題