我有一个集合
TList<TActivityCategory>
TActivityCategory 有一个字符串类型的 Name 属性,我想使用 Name 属性搜索 TList。
我在 TList<> 中看到 BinarySearch,但这需要 TActivityCategory 的实例。我只想传递一个名称的字符串。
我该怎么做呢?
我有一个集合
TList<TActivityCategory>
TActivityCategory 有一个字符串类型的 Name 属性,我想使用 Name 属性搜索 TList。
我在 TList<> 中看到 BinarySearch,但这需要 TActivityCategory 的实例。我只想传递一个名称的字符串。
我该怎么做呢?
创建列表时,您可以传入比较器。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;
坦率地说,考虑到基于比较器的方法所需的所有样板,编写自己的搜索例程可能是最简单的:
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;
如果您没有要搜索的实例,则必须自己进行搜索。有三种基本方法可以做到这一点:
TDictionary<string, TActivityCategory>
在列表旁边维护一个。无需搜索,但您需要编写一些代码以使两者保持同步。