I am aware that this has recently been posted, yet does not function to my needs.
I have my Array
Quotehttp://
feany
gay
bob
I can remove the first Array index(http://) correctly. However, if I try to remove the second index(feany) it removes the http:// aswell. But wait, there's more. When I remove the last index(bob) it just duplicates the first index(http://) aswell.
Remove Code
For i = 0 To UBound(PhraseList) - 1
If LCase(pA(1)) = LCase(PhraseList(i)) Then
SendW "Removed phrase: " & PhraseList(i), strAccount
PhraseList(i) = vbNullString
ReDim Preserve PhraseList(UBound(PhraseList) - 1)
End If
Next i
Help is appreciatd! ::)
Here's the most basic way to remove an item from an ARRAY. If you'll be doing it often you may want to look into a collection.
1. Create a new temporary array, dimensioned to (size - 1) of your start array.
2. Loop throguh your start array, copying everything but the index you want to remove. The temp array now contains your entire start array except the item you want to remove.
3. Redimension your start array to the size of the temp array.
4. Copy the temp array into the start array.
Quote from: Stealth on March 22, 2004, 02:04 PM
Here's the most basic way to remove an item from an ARRAY. If you'll be doing it often you may want to look into a collection.
1. Create a new temporary array, dimensioned to (size - 1) of your start array.
2. Loop throguh your start array, copying everything but the index you want to remove. The temp array now contains your entire start array except the item you want to remove.
3. Redimension your start array to the size of the temp array.
4. Copy the temp array into the start array.
I'll try a collection...thnx
Quote from: CrAz3D on March 22, 2004, 02:26 PM
I'll try a collection...thnx
Bah. You learn not!
Just a note, collections are much slower and less efficient than arrays, they should be avoided in general...
In addition, you could merely overwrite the array(index) you want to erase with array(index+1) and loop this, after this is finished you resize the array to (Ubound - 1) because the last array value will be a copy of the second to last....
Quote from: Lenny on March 22, 2004, 10:01 PM
Just a note, collections are much slower and less efficient than arrays, they should be avoided in general...
In addition, you could merely overwrite the array(index) you want to erase with array(index+1) and loop this, after this is finished you resize the array to (Ubound - 1) because the last array value will be a copy of the second to last....
That is indeed more efficient than I described. Does it work in all situations?
I did something similar to what Lenny said, but only for one purpose (coincidence, Phraseban!) and it seems to work fine. I can't explain it too well... but I'll just paste my code up here to see if you can get the idea. I haven't used it a lot, but with the little I have used it, it functions well.
Dim i As Integer
Dim RFP As Integer
If Phrasebans(0) = "" Then Exit Sub
For i = 0 To UBound(Phrasebans)
If LCase(Mid$(Message, 11)) = LCase(Phrasebans(i)) Then
Phrasebans(i) = ""
For RFP = i To UBound(Phrasebans)
If Phrasebans(RFP) = "" And RFP < UBound(Phrasebans) Then
Phrasebans(RFP) = Phrasebans(RFP + 1)
Phrasebans(RFP + 1) = ""
End If
Next RFP
If UBound(Phrasebans) = 0 Then
Phrasebans(0) = ""
Else
ReDim Preserve Phrasebans(0 To UBound(Phrasebans) - 1)
End If
Exit For
End If
Next i
That appears to be exactly what Lenny described.
uhh, I think Stealth has a good way, thats what I use.
I read collections are slower if working
with about 100 items or less.
I don't use collections
so I can't give an opinion on that.
If the array does not need to be
in an order of any kind.
If a string.. switch the descriptor with last item
If a value.. item to remove equal to last item
last item not neccessarily the ubound,
and then zero out the last item
to kill off the extra item,
depending on how you want to handle it.
Quote from: Lenny on March 22, 2004, 10:01 PM
Just a note, collections are much slower and less efficient than arrays, they should be avoided in general...
Where did you find this information? I was assuming that collections were some kind of binary tree which would make them very efficient for things like removing an item from the middle, looking up an item from a key, growing and shrinking.
http://www.mvps.org/vb/hardcore/html/collections201indexing.htm (http://www.mvps.org/vb/hardcore/html/collections201indexing.htm)
and
http://www.mvps.org/vb/hardcore/html/walkingclistcollection.htm (http://www.mvps.org/vb/hardcore/html/walkingclistcollection.htm)
From what I see an Array is better in most opinions & according to facts. I will redo it to use an Array instead, thank you all.
There still seems to be a few problems that I cannot fiugre out.
Quote[8:05:42 AM] «CrAz3D[xL]» \flist
[8:05:42 AM] «0x69» Current Filters are: http, stealth, bob, gay, feany, telrin
[8:05:46 AM] «CrAz3D[xL]» \frem http
[8:05:46 AM] «0x69» Removed filter: http
[8:05:48 AM] «CrAz3D[xL]» \flist
[8:05:48 AM] «0x69» Current Filters are: stealth, bob, gay, feany, telrin
[8:05:53 AM] «CrAz3D[xL]» \frem telrin
[8:05:53 AM] «0x69» Removed filter: telrin
[8:05:55 AM] «CrAz3D[xL]» \flist
[8:05:55 AM] «0x69» Current Filters are: bob, gay, feany, feany
For i = 0 To UBound(FilterList) - 1
If LCase(pA(1)) = LCase(FilterList(i)) Then
SendW "Removed filter: " & FilterList(i), strAccount
FilterList(i) = FilterList(i + 1)
ReDim Preserve FilterList(UBound(FilterList) - 1)
End If
Next i
I have a feeling the it is the "ReDim Preserve" portion that I am screwing up.
Your ReDim statement appears correct.
FilterList(i) = FilterList(i + 1)
This however only moves the next element into the current's position - not all subsequent elements in the array. If 'i' is at the end of the array an out of bounds error may occur if you try accessing the next element that is not there. I cannot see how your first element is removed though.
hmm, ok...I'll mess w/the Filterlist - w/e
assumes:
Filters() = your filter list
removing = string you want to remove
dim tmp() as string
redim tmp(0)
for i = 0 to ubound(filters)
if lcase(filters(i)) <> lcase(removing) and filters(i) <> "" then
tmp(ubound(tmp)) = filters(i)
redim preserve tmp(ubound(tmp) + 1)
end if
next i
redim preserve tmp(ubound(tmp) - 1)
redim filters(ubound(filters) - 1)
filters = tmp
This is just something I typed up real fast, so there's bound to be an error somewhere, or it might not work at all ;)
[edit 1] fixed code tags
[edit 2] fixed code typos
That's basically what I ended up doing, it wokrs fine now. Thanks
oh ok, I tryed ;D
I did a small test of the laziest possible coding. In this test, a collection is more than 20 times faster than an array.
Command1: 0.5 seconds data generation
Command2: 49 seconds for an array
Command3: 2.2 seconds for a collection
Option Explicit
Dim testdata(100000) As String
Dim removedata(1000) As String
Private Sub swap(a As String, b As String)
Dim tmp As String
tmp = a
a = b
b = tmp
End Sub
Private Sub Command1_Click()
Dim t
t = Timer
Dim i As Long
For i = 0 To 100000
testdata(i) = i
Next i
For i = 0 To 100000
swap testdata(i), testdata(Rnd * 100000)
Next i
For i = 0 To 1000
removedata(i) = testdata(Fix(Rnd * 100) * 1000 + i)
Next i
MsgBox Timer - t
End Sub
Private Sub Command2_Click()
Dim t
t = Timer
Dim ar() As String
Dim i As Long, j As Long, k As Long
For i = 0 To 100000
ReDim Preserve ar(i) As String
ar(i) = testdata(i)
Next i
For i = 0 To 1000
For j = 0 To UBound(ar)
If ar(j) = removedata(i) Then
For k = j To UBound(ar) - 1
ar(k) = ar(k + 1)
Next k
Exit For
End If
Next j
Next i
MsgBox Timer - t
End Sub
Private Sub Command3_Click()
Dim t
t = Timer
Dim i As Long
Dim co As New Collection
For i = 0 To 100000
co.Add testdata(i), testdata(i)
Next i
For i = 0 To 1000
co.Remove removedata(i)
Next i
MsgBox Timer - t
End Sub
Well, now that I am utterly confused on which to use I'll just ask for more opinions. Any?
Quote from: CrAz3D on March 23, 2004, 07:16 PM
Well, now that I am utterly confused on which to use I'll just ask for more opinions. Any?
You have just read the results of an actual test, and you ask for opinions? Either verify the test yourself or find refuting evidence. Other opinions are useless in the face of evidence.
Quote from: Grok on March 23, 2004, 10:10 PM
Quote from: CrAz3D on March 23, 2004, 07:16 PM
Well, now that I am utterly confused on which to use I'll just ask for more opinions. Any?
You have just read the results of an actual test, and you ask for opinions? Either verify the test yourself or find refuting evidence. Other opinions are useless in the face of evidence.
From what I read in about posted links it said that arrays were more effective.
Quote from: CrAz3D on March 23, 2004, 10:22 PM
From what I read in about posted links it said that arrays were more effective.
The answer is that neither is more effective
always, it depends on what you want to do. If you need to find an item and then remove it from the middle (which seemed to be what this question was about) then using a collection may be more effective. Of course, simple optimizations such as reordering the array instead of moving all items up, not rediming it all the time etc may make an array faster.
I chose to use code like that which has been posted here in this thread for the array, and the simplest possible code for the collection.
What is a collection, I've always used arrays within VB. Are they much like linked lists?
Quote from: drivehappy on March 24, 2004, 11:30 AM
What is a collection, I've always used arrays within VB. Are they much like linked lists?
I don't know how they are really implemented. They look to me like a c++ map<string, void*>. They are probably good at things that linked lists are good at, but also at looking up items from a string. They have a higher overhead than arrays. I think that a VB array is treated as a native data structure that the compiler can optimize while accessing a collection always means making a function call.
Started new project
copy and pasted code
placed 4 command buttons on form
compiled into executable
ran executable
clicked in order..
command_1 1.097656
command_2 108.5273
command_3 42.46094
command_4 16.5
My results came out differently..
Is there something else I have to add to the project?
command_4 is just my version of command_2
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Private Sub Command4_Click()
Dim t As Long
Dim i As Long
Dim j As Long
Dim P As Long
Dim C As Long
Dim TEMPdata() As String
t = Timer
For i = 0 To 100000
ReDim Preserve TEMPdata(i) As String
TEMPdata(i) = testdata(i)
Next i
For i = 0 To 1000
P = UBound(TEMPdata)
For j = 0 To P
If removedata(i) = TEMPdata(j) Then
C = StrPtr(TEMPdata(P))
CopyMemory ByVal VarPtr(TEMPdata(P)), ByVal VarPtr(TEMPdata(j)), 4
CopyMemory ByVal VarPtr(TEMPdata(j)), C, 4
ReDim Preserve TEMPdata(P - 1) As String
Exit For
End If
Next j
Next i
MsgBox Timer - t
End Sub
Add-On:
I was expecting command_3 to take less then 10 seconds. Any ideas?
Quote from: o.OV on March 24, 2004, 01:23 PM
Started new project
copy and pasted code
placed 4 command buttons on form
compiled into executable
ran executable
clicked in order..
command_1 1.097656
command_2 108.5273
command_3 42.46094
command_4 16.5
My results came out differently..
Is there something else I have to add to the project?
No, I just verified it, trying it in both vb5 and vb6 and with p-code and native code. Native code cuts my array time down to ~30 seconds, and collection code to around 1.8 seconds. Command3 never reaches 3 seconds.
The collection seems to use about twice as much memory. Perhaps you're low on memory?
Yea.. maybe low memory.
196 megabytes of memory is considered
inadequate by most. heh ;D
and my processor is a 500mhz amd
Add-On:
And I did reboot before running.
I had at least 75 megabytes
of physical memory available at run time.
If memory really is a problem..
I am better off with a simple array.
But I want to test this collection thing anyways.
I'm gonna go and cut the array sizes down
and see if that helps.
Adron, I need you to confirm that my changes were made correctly.
list of changes:
Timer is now GetTickCount
100000 is now 1000
command_1 has been modified
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Private Declare Function GetTickCount Lib "kernel32" () As Long
Dim testdata(1000) As String
Dim removedata(1000) As String
Private Sub swap(a As String, b As String)
Dim tmp As String
tmp = a
a = b
b = tmp
End Sub
Private Sub Command1_Click()
Dim t
t = GetTickCount
Dim i As Long
For i = 0 To 1000
testdata(i) = i
removedata(i) = i
Next i
For i = 0 To 1000
swap testdata(i), testdata(Rnd * 1000)
swap removedata(i), removedata(Rnd * 1000)
Next i
MsgBox GetTickCount - t
End Sub
Private Sub Command2_Click()
Dim t
t = GetTickCount
Dim ar() As String
Dim i As Long, j As Long, k As Long
For i = 0 To 1000
ReDim Preserve ar(i) As String
ar(i) = testdata(i)
Next i
For i = 0 To 1000
For j = 0 To UBound(ar)
If ar(j) = removedata(i) Then
For k = j To UBound(ar) - 1
ar(k) = ar(k + 1)
Next k
Exit For
End If
Next j
Next i
MsgBox GetTickCount - t
End Sub
Private Sub Command3_Click()
Dim t
t = GetTickCount
Dim i As Long
Dim co As New Collection
For i = 0 To 1000
co.Add testdata(i), testdata(i)
Next i
For i = 0 To 1000
co.Remove removedata(i)
Next i
MsgBox GetTickCount - t
End Sub
Private Sub Command4_Click()
Dim t As Long
Dim i As Long
Dim j As Long
Dim P As Long
Dim C As Long
Dim TEMPdata() As String
t = GetTickCount
For i = 0 To 1000
ReDim Preserve TEMPdata(i + 1) As String
TEMPdata(i) = testdata(i)
Next i
For i = 0 To 1000
P = UBound(TEMPdata)
For j = 0 To P
If removedata(i) = TEMPdata(j) Then
C = StrPtr(TEMPdata(P))
CopyMemory ByVal VarPtr(TEMPdata(P)), ByVal VarPtr(TEMPdata(j)), 4
CopyMemory ByVal VarPtr(TEMPdata(j)), C, 4
ReDim Preserve TEMPdata(P - 1) As String
Exit For
End If
Next j
Next i
MsgBox GetTickCount - t
End Sub
Private Sub Command1_Click()
Dim t
t = Timer
Dim i As Long
For i = 0 To 100000
testdata(i) = i
Next i
For i = 0 To 100000
swap testdata(i), testdata(Rnd * 100000)
Next i
For i = 0 To 1000
removedata(i) = testdata(Fix(Rnd * 100) * 1000 + i)
Next i
MsgBox Timer - t
End Sub
I understand what Command2 & 3 are, but what is Command1 exactly? I read that it is a data generation, but what does a data generation do?
Creates a set of sample data for use in testing the speed of the array/collection.
Oh, heh. Silly me. Thanks
Quote from: o.OV on March 25, 2004, 02:13 AM
Adron, I need you to confirm that my changes were made correctly.
list of changes:
Timer is now GetTickCount
100000 is now 1000
command_1 has been modified
Changing it from 100000 to 1000 is a huge change. I don't think you'll get very testable results from that because times should decrease too much, as in a collection going from 2 seconds to 0.02, which is close to how small times VB can measure.
Quote from: Adron on March 25, 2004, 05:31 PM
Quote from: o.OV on March 25, 2004, 02:13 AM
Adron, I need you to confirm that my changes were made correctly.
list of changes:
Timer is now GetTickCount
100000 is now 1000
command_1 has been modified
Changing it from 100000 to 1000 is a huge change. I don't think you'll get very testable results from that because times should decrease too much, as in a collection going from 2 seconds to 0.02, which is close to how small times VB can measure.
I only decreased it like this because memory
may have been a problem.
About the timing..
milliseconds seem to work well enough.
The results are consistent in the order of ranking.
command_1 25ms
command_2 1406ms
command_3 374ms
command_4 122
I'm still puzzled as to why command_3
still isn't performing to expectations for me.
the memory usage for the collection should be
about 100 times smaller..
so it can't still be a problem with memory..
can it?
Yes, that's strange... I'd love to see some results from other people - try the code and post whether my or o.OV's results are odd.
QuoteNative Fast:
com1:.171
com2:12.283
com3:.968
com4:5.015
Native Small:
com1:.171
com2:12.656
com3:1.015
com4:5.171
Native No:
com1:.171
com2:12.437
com3:.984
com4:5.796
PCode:
com1:.203
com2:20.640
com3:1.031
com4:9.687
All seem to work for me
(com4 is o.Ov's)
Hmmk, so, the odd results are o.OV's. Now I wonder why he's getting so bad results for collections...
*gives computer a mean kick* >:(
I'm gonna go check MSDN for anything relevant to my odd results.
http://www.experts-exchange.com/Programming/Programming_Languages/Visual_Basic/Q_20873546.html
Doesn't really account for the time differences between Adron's results and O.o's but it could possibly be the removal of the collections elements causing some delay on lower memory systems.