开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜