我无法理解从GENERIC SEARCH修改解决方案 因为我的课程更复杂,我需要创建几个不同的搜索功能
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));
.....
假设我的TActivityCategory看起来像
TActivityCategory = class
FirstName : String;
Secondname : String;
onemore .....
end;
如何实现搜索我的activtity类中的每个String?
答案 0 :(得分:6)
在你的位置,我会写一个TObjectList的子类,并添加一个如下所示的自定义搜索方法:
TSearchableObjectList<T:class> = class(TObjectList<T>)
public
function Search(aFound: TPredicate<T>): T;
end;
该方法的实现是
function TSearchableObjectList<T>.Search(aFound: TPredicate<T>): T;
var
item: T;
begin
for item in Self do
if aFound(item) then
Exit(item);
Result := nil;
end;
此方法的一个示例是
var
myList: TSearchableObjectList<TActivitycategory>;
item: TActivitycategory;
searchKey: string;
begin
myList := TSearchableObjectList<TActivitycategory>.Create;
// Here you load your list
searchKey := 'WantedName';
// Let´s make it more interesting and perform a case insensitive search,
// by comparing with SameText() instead the equality operator
item := myList.Search(function(aItem : TActivitycategory): boolean begin
Result := SameText(aItem.FirstName, searchKey);
end);
// the rest of your code
end;
上面使用的TPredicate<T>
类型在SysUtils
中声明,因此请务必将其添加到您的uses子句中。
我相信这是我们在Delphi中最接近lambda表达式的方法。
答案 1 :(得分:3)
TList支持使用线性搜索或二进制搜索来搜索项目。通过二进制搜索,该算法采用排序。这不适合您的需求。线性搜索在我看来是你需要的,它可以通过Contains方法获得。
问题是Contains假设您正在搜索T的整个实例。您想将单个字符串传递给Contains但它不会接受它。在你的情况下,它想要一个完整的记录。
您可以提供仅比较单个字段的Comparer。然后传递包含仅指定一个字段的记录。但那很难看。坦率地说,在搜索和排序方面,这个类的设计非常薄弱。在我看来,比较器是状态变量而不是参数这一事实令人震惊。
最重要的是,TList不会轻易提供你想要的东西而不诉诸丑陋。您应该在列表中实现旧式循环以查找匹配项。
请注意,我假设您要提供单个字符串并搜索具有与字符串匹配的字段的条目。实际上,如果您确实希望提供完整的记录并匹配每个字段,那么Contains会根据字典顺序使用合适的Comparer来满足您的需求。