2012-02-15 5 views
3

나는 간단한 StringList.sort를하고 있지만, Delphi는 안정된 정렬이 아닌 QuickSort를 사용합니다. 즉, 동일한 키를 가진 레코드의 상대적 순서를 변경할 수 있습니다.어떻게 StringList.Sort를 Delphi에서 안정적인 정렬로 대체 할 수 있습니까?

안정적인 정렬을 사용해야합니다. 이것을 구현하는 가장 쉬운 방법은 무엇입니까?


Mike 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 루틴에서는 "결과가 0이면 결과 : = Index1 <인덱스 2"일뿐입니다. 하위 지수를 상위 지수보다 낮게 유지하지 않을 것입니까? 그것은 정확하지 않습니다, 그럼 당신은 객체를 할당하지 않아도됩니다. – lkessler

+0

@lkessler는 처음에는 컴파일되지 않지만 무슨 뜻인지 알 수 있습니다. 그래도 작동하지 않습니다. 최종 목적지로가는 도중 두 항목이 서로 바뀌지 않도록하는 방법은 없습니다. –

+0

나는 그렇게 생각하지 않는다. QuickSort는 서로 다른 두 문자열을 비교하기 전에 두 문자열을 서로 바꿀 수 있습니다. 그 시점에서 원래 색인을 잃어 버렸습니다. 원래 색인은 안정성을 위해 중요한 것입니다. –