10

可能重复:
如何在通用 TList 中搜索具有特定字段值的记录?

我有一个集合

TList<TActivityCategory>

TActivityCategory 有一个字符串类型的 Name 属性,我想使用 Name 属性搜索 TList。

我在 TList<> 中看到 BinarySearch,但这需要 TActivityCategory 的实例。我只想传递一个名称的字符串。

我该怎么做呢?

4

3 回答 3

5

创建列表时,您可以传入比较器。Generics.Defaults 单元中有一些比较器类,您可以在其中传入一些匿名方法来比较两个元素。它们用于多种方法,例如 IndexOf、Contains 或 Sort。

例子:

uses
  Generics.Defaults,
  Generics.Collections;

type
  TActivityCategory = class
  private
    FName: string;
  public
    constructor Create(const Name: string);
    property Name: string read FName write FName;
  end;

constructor TActivityCategory.Create(const Name: string);
begin
  FName := Name;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  activities: TList<TActivityCategory>;
  search: TActivityCategory;
begin
  activities := TObjectList<TActivityCategory>.Create(
    TDelegatedComparer<TActivityCategory>.Create(
      function(const Left, Right: TActivityCategory): Integer
      begin
        Result := CompareText(Left.Name, Right.Name);
      end));

  activities.Add(TActivityCategory.Create('Category B'));
  activities.Add(TActivityCategory.Create('Category C'));
  activities.Add(TActivityCategory.Create('Category A'));

  search := TActivityCategory.Create('Category C');
  if activities.Contains(search) then
    ShowMessage('found');

  ShowMessageFmt('Index: %d', [activities.IndexOf(search)]);
  activities.Sort;
  ShowMessageFmt('Index: %d', [activities.IndexOf(search)]);


  search.Name := 'Category D';
  if not activities.Contains(search) then
    ShowMessage('not found');

  search.Free;
  activities.Free;
end;
于 2011-11-08T19:05:12.383 回答
2

坦率地说,考虑到基于比较器的方法所需的所有样板,编写自己的搜索例程可能是最简单的:

type
  TActivityCategoryList = class(TList<TActivityCategory>)
  public
    function Find(const Name: string): Integer;
  end;

function TActivityCategoryList.Find(const Name: string): Integer;
begin
  for Result := 0 to Count-1 do
    if Self[Result].Name=Name then
      exit;
  Result := -1;
end;
于 2011-11-08T19:54:55.733 回答
1

如果您没有要搜索的实例,则必须自己进行搜索。有三种基本方法可以做到这一点:

  • 二分查找:实现自己的二分查找。这仅在列表已排序时才有效。
  • 线性搜索:实现自己的线性搜索。这将始终有效,但在大型列表中它比二进制搜索慢得多。
  • 字典查找:TDictionary<string, TActivityCategory>在列表旁边维护一个。无需搜索,但您需要编写一些代码以使两者保持同步。
于 2011-11-08T17:32:57.980 回答