2

I have a TMemo on a form which allows users to enter a list of items. People can enter many items here. When they click Save the contents of the TMemo is checked and then added to the database.

I have a second list in a TStringList which I loop over and check to see if any of it's items are contained in the TMemo.

In a nut shell it looks like this

....
//slItems = TStringList
//mItems = TMemo
for i := slItems.Count -1 downto 0 do
begin
  if mItems.Lines.IndexOf(slItems[i]) = -1 then
    slItems[i].Delete;
end;
----

So stringlist looped, check to see if it exists in memo, if not delete from list.

However, with 200+ items this is starting to slow down a lot, and with 1000 it gets real bad.

Whats the fastest way to search a TMemo?

Wizzard
  • 12,582
  • 22
  • 68
  • 101

1 Answers1

7

Read all of TMemo into a local TStringList and work from that. Every time you're accessing TMemo.Lines you're relying on Windows messaging to talk to the windows-provided multi line text box. Anything but efficient!

....
//slItems = TStringList
//mItems = TMemo
//L = TStringList
L.Text := mItems.Text; // edited per David's suggestion.
L.Sorted := True; // per Uwe Raabe's suggestion.
for i := slItems.Count -1 downto 0 do
begin
  if L.IndexOf(slItems[i]) = -1 then
    slItems[i].Delete;
end;
----
Wizzard
  • 12,582
  • 22
  • 68
  • 101
Cosmin Prund
  • 25,498
  • 2
  • 60
  • 104
  • 4
    `StringList.Text := Memo.Text` is the quick way to do this. – David Heffernan Apr 11 '11 at 12:48
  • @David, I've always used the `Assign()`; I've just looked what `TStrings.Assign(TStrings)` does and it's a horror story... Thank you very much for the tip. – Cosmin Prund Apr 11 '11 at 12:55
  • 3
    As the order of the items in L is of no relevance, add `L.Sort` before the loop and you should go much faster. – Uwe Raabe Apr 11 '11 at 14:28
  • @Uwe, `L.Sorted := True` makes it fast, `L.Sort` doesn't. – Cosmin Prund Apr 11 '11 at 14:45
  • Made it CW, because out of 3 lines of code added to the OP's code, two came from peer comments. – Cosmin Prund Apr 11 '11 at 14:48
  • It's faster when sorted because binary search can be used, but the string list can only take advantage of this when it *knows* that it is ordered. That's why it's not enough just to sort the list, you have to tell the list that it has been sorted too. – David Heffernan Apr 11 '11 at 14:55
  • Yes +1 for sort, it speeds things up as it uses binary search. – Runner Apr 11 '11 at 14:57
  • I don't know why calling sort does not set Sorted to true. It should. – Runner Apr 11 '11 at 15:01
  • @Runner, it shouldn't. When the list is `Sorted := True`, if you add something, it's placed in sorted order; If the list is not sorted, is added as the last element of the list. – Cosmin Prund Apr 11 '11 at 15:12
  • @David, @Cosmin: There's nothing horrible about `TStrings.Assign`. Instead of just copying text, it makes sure other settings are identical, and that string/object association is preserved. Assigning `.Text` won't do any of those things. – Mason Wheeler Apr 11 '11 at 17:10
  • 1
    @mason for a memo there's nothing but the strings so what you want is a simple WM_GETTEXT as I suggested. – David Heffernan Apr 11 '11 at 17:34