2012-02-15 17 views
3

私は単純なStringList.sortをやっていますが、DelphiはQuickSortを使用しています。これは安定したソートではないため、等しいキーでレコードの相対順序が変更される可能性があります。DelphiでStringList.SortをStableソートに置き換える方法はありますか

私は安定した並べ替えを使用する必要があります。これを実装する最も簡単な方法は何ですか?


マイクWの答えは、あまりコードを変更しなくても簡単に行うことができます。

ありがとう、マイク。

+0

は、このヘルプをしていますか? [TListとTStringListに安定したソートを追加する簡単な方法](http://stackoverflow.com/questions/7907220/easy-way-to-add-stable-sorting-to-tlist-and-tstringlist) - 参照用のリンクを追加するだけです) –

+0

@KenWhite - そのリンクをありがとう。見逃した。しかし、答えはあなた自身の並べ替えを書くことでした。確かに、StringListの安定した並べ替えを使いたいと思っている10,000人が、自分自身を見つけ出して書き出す必要がなくなるよりも、どこかに簡単なことがあるはずです。 – lkessler

+1

これは、 'TStringList.CustomSort'のためのものです。組み込みQuickSortのための独自の書き換えを書くことができます。あなたが含まれているもの以外の何かをしたい場合は、自分で書く必要があります。 :)あなた自身の 'TStringList'子孫を書くことができ、独自の' Sort'を実装することができます。バーチャルなので、オーバーライドすることができます。 –

答えて

11

文字列リストのObjectsプロパティをまだ使用していない場合は、オブジェクトプロパティの元の位置を整数として格納することが迅速かつ解決しない場合があります。元の位置を考慮して独自の安定した並べ替え比較関数を提供することができます。あなたがあなた自身のコードで行う必要があるだろうすべてはちょうどCustomSortを呼び出す前に、オブジェクトのプロパティを割り当てるリスト全体を反復です:

function StableSortCompare(List: TStringList; Index1, Index2: Integer): Integer; 
begin 
    result := CompareStr(List[Index1], List[Index2]); 
    if result = 0 then result := integer(List.Objects[Index1]) - integer(List.Objects[Index2]); 
end; 

procedure TSortTestForm.SortButtonClick(Sender: TObject); 
var 
    SL : TStringList; 
    i : integer; 
begin 
    SL := TStringList.Create; 
    try 
    SL.AddObject('One', pointer(0)); 
    SL.AddObject('One', pointer(1)); 
    SL.AddObject('One', pointer(2)); 
    SL.AddObject('Two', pointer(3)); 
    SL.AddObject('Two', pointer(4)); 
    SL.AddObject('One', pointer(5)); 
    SL.AddObject('One', pointer(6)); 
    SL.AddObject('One', pointer(7)); 
    // SL.Sort; // Try instead of custom sort to see difference 
    SL.CustomSort(StableSortCompare); 
    for i := 0 to SL.Count-1 do begin 
     Memo1.Lines.Add(Format('Text: %s Orig Pos: %d', [SL[i], integer(SL.Objects[i])])); 
    end; 
    finally 
    SL.Free; 
    end; 
end; 
+1

それは実際にそれほど悪くはありません。しかし、なぜStableSortCompareルーチンでは、 "result = 0の場合はresult = = Index1 lkessler

+0

@lkesslerはコンパイルしませんが、最初は意味が分かります。しかし、それは動作しません。 2つのアイテムが最終目的地にスワップされるのを止めるものは何もありません。 –

+0

私はそうは思わない。クイックソートは、2つの異なる文字列を交換してから、同じものを比較しようとする場合があります。その時点で、安定性のために重要な元のインデックスを失ってしまいました。 –