Search the general list

It’s hard for me to figure out how to change the solution from GENERIC SEARCH since my class is more complex and I need to create several different search functions

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)); ..... 

Suppose my TActivityCategory looks like

  TActivityCategory = class FirstName : String; Secondname : String; onemore ..... end; 

How to implement a search for each row inside an activtity class?

+2
source share
2 answers

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; 

Implementation for this method

 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 section.

I believe this is the closest to what we can get in lambda expressions in Delphi.

+6
source

TList supports searching for elements using linear or binary search. In binary search, the algorithm involves ordering. This is not suitable for your needs. The linear search seems to me what you need and is accessible through the Contains method.

The problem is that Contains assumes that you are looking for the whole instance of T. You want to pass one line to Contains, but it will not accept this. He wants a complete record in your case.

You can provide Comparer, which compares only one field. And then pass Contains an entry with only one field specified. But that is pretty ugly. Honestly, the design of this class is very weak when it comes to searching and sorting. The fact that the comparator is a state variable and not a parameter is a shocking failure in my opinion.

The bottom line is that TList does not always offer what you are looking for without resorting to ugliness. You should probably implement a vintage fashion cycle on the list to find a match.

Note that I am assuming that you want to provide a single row and look for a record that has a field corresponding to the row. If you really want to provide a complete record and map each field, then Contains does what you need with a suitable Comparer using lexicographic ordering.

+3
source

Source: https://habr.com/ru/post/949804/


All Articles