2011年7月26日

TListの新しいメソッドSortList/IndexOfItem/ExtractItem/RemoveItemとTDirection

Delphi 2010でTListクラスにSortListIndexOfItemExtractItemRemoveItemというメソッドが追加されています。

TList.SortListはQuickSortの比較関数を"const TListSortCompareFunc" = "reference to function(Item2: Pointer, Item1: Pointer): Integer;"、つまり無名メソッドで渡すことができる、というもので、従来のSortのように比較関数を別途記述する必要がありません。たとえばフォーム上にTButtonとTMemoをひとつずつ配置しておき、
type
  TTestItem = class(TObject)
  private
    FNum: Integer;
    FStr: String;
  public
    constructor Create(ANum: Integer; const AStr: String);
    property Num: Integer read FNum;
   property Str: String read FStr;
  end;

constructor TTestItem.Create(ANum: Integer; const AStr: String);
begin
  inherited Create;
  FNum := ANum;
  FStr := AStr;
end;

procedure TForm1.Button1Click(Sender: TObject);

  procedure ShowList(List: TObjectList; const Caption: String);
  var
    Index: Integer;
    TestItem: TTestItem;
  begin
    Memo1.Lines.Add(Caption);
    for Index := 0 to List.Count - 1 do
    begin
      TestItem := List.Items[Index] as TTestItem;
      Memo1.Lines.Add(Format('Num=%d Str=%s',
                             [TestItem.Num,TestItem.Str]));
    end;
    Memo1.Lines.Add('');
  end;

var
  List: TObjectList;
begin

  List := TObjectList.Create(True);
  try
    List.Add(TTestItem.Create(5,'Five'));
    List.Add(TTestItem.Create(3,'Three'));
    List.Add(TTestItem.Create(1,'One'));
    List.Add(TTestItem.Create(2,'Two'));
    List.Add(TTestItem.Create(4,'Four'));

    ShowList(List,'Before sort');

    List.SortList(
      function (Item1, Item2: Pointer): Integer
      begin
        Result := TTestItem(Item1).Num - TTestItem(Item2).Num;
      end);

    ShowList(List,'After sort (Num)');

    List.SortList(
      function (Item1, Item2: Pointer): Integer
      begin
        Result := CompareStr(TTestItem(Item1).Str,TTestItem(Item2).Str);
      end);

    ShowList(List,'After sort (Str)');

  finally
    List.Free;
  end;

end;

こんな感じでSortListのパラメータに直接比較関数を記述できます。無名関数の記述が気持ち悪い(セミコロンの付きかたが違う、とか)という点はともかく、比較関数そのものはわかりやすく書くことができます。

一方IndexOfItem/ExtractItem/RemoveItemはIndexOf/Extract/Removeに追加のパラメータとしてFromBeginning/FromEndという2値の列挙型TList.TDirectionを受け取り、これがFromBeginningならば対象アイテムを(従来通り)先頭から検索し、FromEndならば対象アイテムを末尾から検索するというバリエーションです(なぜオーバロードにせず別のシグネチャを与えたのかはわかりません)。

元ねたはMarco CantuさんDelphi 2010 Handbook

0 件のコメント: