Author | Message | Time |
---|---|---|
CrAz3D | I am aware that this has recently been posted, yet does not function to my needs. I have my Array [quote]http:// feany gay bob[/quote] 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 [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[/code] Help is appreciatd! ::) | March 22, 2004, 7:47 PM |
Stealth | 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. | March 22, 2004, 8:04 PM |
CrAz3D | [quote author=Stealth link=board=31;threadid=5914;start=0#msg50910 date=1079985897] 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] I'll try a collection...thnx | March 22, 2004, 8:26 PM |
Grok | [quote author=CrAz3D link=board=31;threadid=5914;start=0#msg50916 date=1079987170] I'll try a collection...thnx [/quote] Bah. You learn not! | March 23, 2004, 2:20 AM |
Lenny | 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.... | March 23, 2004, 4:01 AM |
Stealth | [quote author=Lenny link=board=31;threadid=5914;start=0#msg51067 date=1080014464] 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] That is indeed more efficient than I described. Does it work in all situations? | March 23, 2004, 4:25 AM |
Flame | 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. [code] 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 [/code] | March 23, 2004, 4:40 AM |
Stealth | That appears to be exactly what Lenny described. | March 23, 2004, 5:44 AM |
Fr0z3N | uhh, I think Stealth has a good way, thats what I use. | March 23, 2004, 6:06 AM |
o.OV | 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. | March 23, 2004, 6:50 AM |
Adron | [quote author=Lenny link=board=31;threadid=5914;start=0#msg51067 date=1080014464] Just a note, collections are much slower and less efficient than arrays, they should be avoided in general... [/quote] 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. | March 23, 2004, 11:14 AM |
Grok | March 23, 2004, 11:56 AM | |
CrAz3D | 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[/quote] [code]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[/code] I have a feeling the it is the "ReDim Preserve" portion that I am screwing up. | March 23, 2004, 2:58 PM |
drivehappy | Your ReDim statement appears correct. [code] FilterList(i) = FilterList(i + 1) [/code] 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. | March 23, 2004, 4:45 PM |
CrAz3D | hmm, ok...I'll mess w/the Filterlist - w/e | March 23, 2004, 4:50 PM |
Eli_1 | assumes: Filters() = your filter list removing = string you want to remove [code] 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 [/code] 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 | March 23, 2004, 7:38 PM |
CrAz3D | That's basically what I ended up doing, it wokrs fine now. Thanks | March 23, 2004, 7:45 PM |
Eli_1 | oh ok, I tryed ;D | March 23, 2004, 7:50 PM |
Adron | 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 [code] 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 [/code] | March 23, 2004, 10:33 PM |
CrAz3D | Well, now that I am utterly confused on which to use I'll just ask for more opinions. Any? | March 24, 2004, 1:16 AM |
Grok | [quote author=CrAz3D link=board=31;threadid=5914;start=15#msg51270 date=1080090984] Well, now that I am utterly confused on which to use I'll just ask for more opinions. Any? [/quote] 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. | March 24, 2004, 4:10 AM |
CrAz3D | [quote author=Grok link=board=31;threadid=5914;start=15#msg51331 date=1080101417] [quote author=CrAz3D link=board=31;threadid=5914;start=15#msg51270 date=1080090984] Well, now that I am utterly confused on which to use I'll just ask for more opinions. Any? [/quote] 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 what I read in about posted links it said that arrays were more effective. | March 24, 2004, 4:22 AM |
Adron | [quote author=CrAz3D link=board=31;threadid=5914;start=15#msg51334 date=1080102126] From what I read in about posted links it said that arrays were more effective. [/quote] 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. | March 24, 2004, 3:09 PM |
drivehappy | What is a collection, I've always used arrays within VB. Are they much like linked lists? | March 24, 2004, 5:30 PM |
Adron | [quote author=drivehappy link=board=31;threadid=5914;start=15#msg51428 date=1080149423] What is a collection, I've always used arrays within VB. Are they much like linked lists? [/quote] 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. | March 24, 2004, 5:56 PM |
o.OV | 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 [code] 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 [/code] Add-On: I was expecting command_3 to take less then 10 seconds. Any ideas? | March 24, 2004, 7:23 PM |
Adron | [quote author=o.OV link=board=31;threadid=5914;start=15#msg51461 date=1080156227] 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? [/quote] 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? | March 24, 2004, 7:38 PM |
o.OV | 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. | March 24, 2004, 7:50 PM |
o.OV | 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 [code] 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 [/code] | March 25, 2004, 8:13 AM |
CrAz3D | [code]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[/code] 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? | March 25, 2004, 4:11 PM |
Stealth | Creates a set of sample data for use in testing the speed of the array/collection. | March 25, 2004, 8:04 PM |
CrAz3D | Oh, heh. Silly me. Thanks | March 25, 2004, 8:43 PM |
Adron | [quote author=o.OV link=board=31;threadid=5914;start=15#msg51598 date=1080202431] 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 [/quote] 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. | March 25, 2004, 11:31 PM |
o.OV | [quote author=Adron link=board=31;threadid=5914;start=30#msg51672 date=1080257481] [quote author=o.OV link=board=31;threadid=5914;start=15#msg51598 date=1080202431] 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 [/quote] 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] 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? | March 26, 2004, 9:20 AM |
Adron | 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. | March 26, 2004, 4:43 PM |
CrAz3D | [quote]Native 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[/quote] All seem to work for me (com4 is o.Ov's) | March 26, 2004, 7:24 PM |
Adron | Hmmk, so, the odd results are o.OV's. Now I wonder why he's getting so bad results for collections... | March 26, 2004, 8:15 PM |
o.OV | *gives computer a mean kick* >:( I'm gonna go check MSDN for anything relevant to my odd results. | March 27, 2004, 4:06 AM |
drivehappy | 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. | March 27, 2004, 8:31 AM |