I \'m trouble understanding in modifying the solution from GENERIC SEARCH as my class is more complex and I need to create several different search functions
pro
TList supports searching for items using either linear or binary search. With binary search, the algorithm assumes an ordering. That's not appropriate for your needs. Linear search seems to me to be what you need, and it's available through the Contains method.
The problem is that Contains assumes that you are searching for an entire instance of T. You want to pass a single string to Contains but it won't accept that. It wants a complete record, in your case.
You could provide a Comparer that only compares a single field. And then pass Contains a record with just that one field specified. But that's pretty ugly. Frankly the design of this class is very weak when it comes to searching and sorting. The fact that the comparer is a state variable rather than a parameter is a shocking lapse in my view.
The bottom line is that TList does not readily offer what you are looking for without resorting to ugliness. You should probably implement an old-fashion loop across the list to look for your match.
Note that I'm assuming you want to provide a single string and search for an entry that has a field matching the string. If in fact you do want to provide a complete record and match every field, then Contains does what you need, with suitable Comparer using a lexicographic ordering.
In your place I would write a subclass of TObjectList and add a custom Search method that would look like this:
TSearchableObjectList<T:class> = class(TObjectList<T>)
public
function Search(aFound: TPredicate<T>): T;
end;
The implementation for that method is
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;
An example of this method is
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;
The TPredicate<T>
type used above is declared in SysUtils
, so be sure to add it to your uses clause.
I believe this is the closest we can get to lambda expressions in Delphi.