Here we go again.
You should use the built-in TList<T>.BinarySearch()
function, even if it rightfully asks for a TEstr
record as a parameter. You'll first need to use TList<T>.Sort()
to sort the list using the same criteria as for the search, then call BinarySearch()
to find your record.
Here's a function that does both (sort and search):
uses Generics.Defaults; // this provides TDelegatedComparer
uses Math; // this provides Sign()
function SearchList(Date:TDate; Sort:Boolean; List:TList<TEstr>): Integer;
var Comparer: IComparer<TEstr>;
Dummy: TEstr;
begin
// Prepare a custom comparer that'll be used to sort the list
// based on Date alone, and later to BinarySearch the list using
// date alone.
Comparer := TDelegatedComparer<TEstr>.Construct(
function (const L, R: TEstr): Integer
begin
Result := Sign(L.Date - R.Date);
end
);
// If the list is not sorted, sort it. We don't know if it's sorted or not,
// so we rely on the "Sort" parameter
if Sort then List.Sort(Comparer);
// Prepare a Dummy TEstr record we'll use for searching
Dummy.Date := Date;
// Call BinarySearch() to look up the record based on Date alone
if not List.BinarySearch(Dummy, Result, Comparer) then
Result := -1;
end;
BinarySearch
assumes the list is sorted (that's the essence of binary searching!). On your first call you need to set Sort=True
so the list is properly sorted. On subsequent calls Sort
should be False
. Of course, in actual use you'd probably have separate routines for searching and sorting, and you'd probably have them as methods of a class descending from TList<TEstr>
(to make things easyer). I places both in the same routine for dempnstration purposes.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…