Delphi - Clean TListBox Items
I want to clean a list box by checking it against two other list boxes.
- Listbox1 would have the big list of items
- Listbox2 would have words I want removed from listbox1
- Listbox3 would have mandatory words that have to exist for it to remain in listbox1
Below is the code I've got so far for this, it's VERY slow with large lists.
// not very efficient
Function che开发者_JS百科cknegative ( instring : String; ListBox : TListBox ) : Boolean;
Var
i : Integer;
Begin
For I := listbox.Items.Count - 1 Downto 0 Do
Begin
If ExistWordInString ( instring, listbox.Items.Strings [i],
[soWholeWord, soDown] ) = True
Then
Begin
result := True; //True if in list, False if not.
break;
End
Else
Begin
result := False;
End;
End;
result:=false;
End;
Function ExistWordInString ( aString, aSearchString : String;
aSearchOptions : TStringSearchOptions ) : Boolean;
Var
Size : Integer;
Begin
Size := Length ( aString );
If SearchBuf ( Pchar ( aString ), Size, 0, 0, aSearchString, aSearchOptions ) <> Nil Then
Begin
result := True;
End
Else
Begin
result := False;
End;
End;
If you do anything that loops with a TStrings
instance in a control it may be beneficial to create a temporary TStringList
instance, assign the control items to it, then use the temporary list.
The reason for that is that the Items
property in a list box, combo box or similar is implemented via a proxy class that doesn't hold the strings itself, but which uses Windows messages like LB_GETCOUNT
and LB_GETTEXT
to retrieve the elements directly from the native Windows control. If you access a string list item several times then the overhead of the repeated message handling will add up.
If this is working on a listbox, it's probably taking a lot of time to repaint everything every time. You can disable this behavior. Surround the outermost loop with this:
listbox.Items.BeginUpdate;
try
//do the loop here
finally
listbox.Items.EndUpdate;
end;
Also, you can assign a boolean directly to the evaluation of a boolean expression, which will save some time on your inner loop. So:
Function ExistWordInString ( aString, aSearchString : String; aSearchOptions : TStringSearchOptions ) : Boolean;
Var
Size : Integer;
Begin
Size := Length ( aString );
result := SearchBuf ( Pchar ( aString ), Size, 0, 0, aSearchString, aSearchOptions ) <> Nil;
End;
Not sure how much of a difference that will make, though. If you make these changes and it's still too slow, try running your program through a profiler such as Sampling Profiler, which will help you see what your code is spending most of its time doing.
精彩评论