Collection, Array, or Listbox?
I'm creating an anagram program and I'm almost done. Currently, I'm adding every word found by my anagram code into a group of listboxex. There's a listbox for 2-letter words, another listbox for 3-letter words, etc. My problem is that I'm getting duplicate words when there are "blanks". A blank can be any letter and that's what causes the duplicates.
I want to totally avoid adding duplicate words to the listboxes because it slows down the program when the list gets long. The word gets added, the list gets resorted, the scrollbars shrink etc.
Is there a command to check if a listbox already contains a word without looping through the whole list?
If I put all the unique words into an array before putting them in the listbox, is there a single command to copy an array of strings to a listbox or do I have to loop through the array and add each item one at a time?
Should I use a collection rather than an array? Does that contain a quick way to see if a word is already found?
Any other ideas on this?
Re: Collection, Array, or Listbox?
You can use SendMessage api to check whether or not item already exists:
Code:
Option Explicit
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, lParam As Any) As Long
Private Const LB_FINDSTRING = &H18F
Private Const LB_FINDSTRINGEXACT = &H1A2
Private Function FindItem(lst As ListBox, strText As String) As Long
Dim iIndex As Integer
iIndex = SendMessage(lst.hwnd, LB_FINDSTRINGEXACT, -1, ByVal strText)
FindItem = iIndex
End Function
'usage:
If FindItem(List1, "whatever") = -1 Then
List1.AddItem = "whatever"
End If
Regarding collection vs array - this could be a good topic for another thread.
While arrays are faster collections have key property so it could be simpler to get specific item.
Re: Collection, Array, or Listbox?
While waiting for a reply I programmed a solution using a string (FoundWordsList$) to hold all of the unique words that were found. It's a long string with each word surrounded by an empty space on each end.
When a new word is "found" I add a space on each end and compare it to FoundWordsList$ using InStrB. If the new word is already in the list, then I just skip it and keep looking for more words. Each time I add a word to FoundWordsList$, I also add it to a ListBox.
With only one wildcard, it's less than half a second to search the whole dictionary. With 2 wildcards and 8 real letters, it's taking around 7 or 8 seconds or more.
Do you think the API call would go faster than the string search?
Re: Collection, Array, or Listbox?
Quote:
Originally Posted by
DroopyPawn
Do you think the API call would go faster than the string search?
Without a single doubt. :)
Re: Collection, Array, or Listbox?
I tried it out and it actually takes about 3 times as long as my code but I was checking 10 different ListBoxes. I'm going to add a hidden ListBox to hold ALL of the words and see if that helps.
Re: Collection, Array, or Listbox?
Nope. Still no good. I even got an overflow error.
Re: Collection, Array, or Listbox?
You can store found words in a String that you hold in memory. This allows for quick searching.
Code:
Dim strWords As String
' to initialize string:
strWords = vbNullChar
' to add a new word:
strWords = strWords & strNewWord & vbNullChar
' to check whether a word exists already:
blnExists = InStr(strWords, vbNullChar & strFindWord & vbNullChar) > 0
Using listboxes for this kind of thing is quite slow. The best you could do is to have string arrays filled up with the words in the listboxes and work with those arrays. Update llistboxes only after you're done with the changes. Thus listboxes would only be for displaying data, like they should be.
Re: Collection, Array, or Listbox?
Quote:
Originally Posted by
DroopyPawn
Nope. Still no good. I even got an overflow error.
It falls on this line:
Dim iIndex As Integer
and it's because your listbox contains more items than integer can hold (32,767) - VB6's Listbox control can only handle up to that amount and after that indexing is messed up.
Try using Lisview control instead - it has built-in FindItem method and it can handle as many items as Long data type can hold.
Re: Collection, Array, or Listbox?
I've rewritten the code so that I only loop through the dictionary word list one time. So there's no possibility of duplicates now - unless my dictionary contains duplicates -- which it doesn't.
Still I wonder....
Would looping through a collection using For/Each go any faster than looping through an array using For/Next? In a For/Next loop, there is a variable that gets incremented and compared to an upper value each time through the loop. Do the same steps occur in a For/Each loop? If not, it might be a little faster - and with more than 170,000 words, any little improvement could help.
Re: Collection, Array, or Listbox?
For Each is slower: it requires an extra background mechanism that gives VB the information on which element to use next. Thus instead of simple incrementation it has some additional processing.
Re: Collection, Array, or Listbox?
In my experience.
Using a Collection is faster.
Using API to check if an item already exists in a listbox might be better in your case though.
List1, Command1, Text1
Quote:
Option Explicit
Dim Col As Collection
Private Sub Form_Initialize()
Set Col = New Collection
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
Set Col = Nothing
End Sub
Private Sub Command1_Click()
On Error Resume Next
Col.Add Text1.Text, Text1.Text 'Collections are not case-sensitive.
If Err.Number <> 457 Then List1.AddItem Text1.Text '457 - Trying to add duplicate error
End Sub