1

I have an Array say: VMHArray = (12,22,34,4) Now have another Arraylist object say ArrayListTaskDetails holding the data as (12,55,44,4,12,22,21,107,43,22,34) Now the below code I wrote to remove items from the list ArrayListTaskDetails which are not present in the VMHArray.

Code

Dim Flag : Flag = true
Dim Counter
For IndexSearch = 0 To ArrayListTaskDetails.Count - 1 step 4

    Counter = 0
    Do while Flag

        If VMHArray(Counter) <> ArrayListTaskDetails (IndexSearch) Then

          ArrayListTaskDetails.RemoveRange IndexSearch, 4
          Flag = False

        End If
    Counter = Counter + 1
    Loop

Next

Now Suppose a match found at IndexSearch = 0,so according it would delete the element at locations 0,1,2,3 - quite good. But due to removal and to make the ArrayList object contiguous by functionality other elements will be shifted by 4 to left. Now the problem is as For Loop already incremented by 4,so it would start from next iteration from location 4. Thus now the new element at 0 location in the array list can never get a chance to test the equality with the VMHArray array elements. Can we handle such scenario without loosing the intended operation or anyway if we can set the For Loop counter to its immediate position,where the just recent match found and 4 elements removed.?

If any issue to understand the problem,let me know please!

EDIT Go to will not work

CODE(as per @Ankit suggestion)

Option Explicit

Dim Flag : Flag = true
Dim Counter
Dim VMHArray : VMHArray = Array(12,22,34,4) 
Dim ArrayListTaskDetails : Set ArrayListTaskDetails = CreateObject("System.Collections.ArrayList")

    ArrayListTaskDetails.Add(45)
    ArrayListTaskDetails.Add(4)
    ArrayListTaskDetails.Add(22)
    ArrayListTaskDetails.Add(4)
    ArrayListTaskDetails.Add(45)
    ArrayListTaskDetails.Add(20)
    ArrayListTaskDetails.Add(12)
    ArrayListTaskDetails.Add(35)
    ArrayListTaskDetails.Add(34)

    Restart:
For IndexSearch = 0 To ArrayListTaskDetails.Count - 1 step 4

    Counter = 0
    Do while Flag

        If VMHArray(Counter) <> ArrayListTaskDetails (IndexSearch) Then

          ArrayListTaskDetails.RemoveRange IndexSearch, 4
          Goto Restart
          Flag = False

        End If
    Counter = Counter + 1
    Loop

Next

MsgBox(Join(ArrayListTaskDetails.ToArray()),"$")

Error

Thanks,

Community
  • 1
  • 1
CodeLover
  • 1,054
  • 6
  • 24
  • 40
  • did you try `exit for` writing a `for` or try [this to exit while loop](http://stackoverflow.com/questions/1271949/exit-a-while-loop-in-vbscripts) – bonCodigo Jan 02 '13 at 13:55
  • @bonCodigo If I used `exit for` then how the rest element will be checked? – CodeLover Jan 02 '13 at 13:57
  • Try the code I have given please. To be very frank, sorry I haven't gone through the entire *full novel text*, just looked at your title and the code. – bonCodigo Jan 02 '13 at 14:07
  • 1
    Just iterate your loop from the last element to the first like `For IndexSearch = ArrayListTaskDetails.Count - 1 To 0 step -4`. This will also circumvent needless looping over elements that are already inspected. – AutomatedChaos Jan 02 '13 at 14:08
  • @AutomatedChaos I am getting the below error:`Cannot use paranthesis when calling Sub` Any help why so? from the line `MsgBox(Join(ArrayListTaskDetails.ToArray()),"$")` – CodeLover Jan 02 '13 at 14:15
  • 1
    @AutomatedChaos - looping backwards is correct, but your starting position is wrong (should be .Count - 4) – Ekkehard.Horner Jan 02 '13 at 14:32
  • @Ekkehard.Horner I agree! you catch a bit bug within the line :) – CodeLover Jan 02 '13 at 14:34
  • 2
    @CodeLover You have your parenthesis of your Join statement placed incorrectly, letting the `,"$"` belong to the MsgBox (the second parameter for Join is optional, that is why you don't get an error on that statement). MsgBox needs to be `call`ed if you want to use parenthesis, otherwise get rid of them. Now, the VBScript engine sees `"$"` as the second (optional) parameter for messagebox and is giving you this warning. – AutomatedChaos Jan 02 '13 at 14:36
  • @Ekkehard.Horner nice find. – AutomatedChaos Jan 02 '13 at 14:43
  • @AutomatedChaos Can you help me here with a tips [Post](http://stackoverflow.com/questions/14119936/i-am-not-able-to-clear-and-reset-the-background-color-of-a-cell#comment19549322_14119936)? – CodeLover Jan 02 '13 at 14:44

2 Answers2

5

Two ideas to solve the problem:

  1. use a dictionary to check for the items to keep
  2. loop backwards

In code:

Option Explicit

Dim alSrc : Set alSrc = CreateObject("System.Collections.ArrayList")
Dim sE
For Each sE In Split("a x x x b x x x c x x x d x x x e x x x f x x x a x x x")
    alSrc.Add sE
Next
WScript.Echo "alSrc:", Join(alSrc.ToArray(), ".")
Dim aKeep   : aKeep       = Split("a d")
WScript.Echo "aKeep:", Join(aKeep, ".")
Dim dicKeep : Set dicKeep = CreateObject("Scripting.Dictionary")
For Each sE In aKeep
    dicKeep(sE) = 0
Next
WScript.Echo "dicKeep:", Join(dicKeep.Keys(), ".")
Dim nI
For nI = alSrc.Count - 4 To 0 Step -4
    sE = alSrc(nI)
    If Not dicKeep.Exists(sE) Then
       alSrc.RemoveRange nI, 4
    End If
    WScript.Echo sE, nI, Join(alSrc.ToArray(), ".")
Next
WScript.Echo "alSrc:", Join(alSrc.ToArray(), ".")

output:

alSrc: a.x.x.x.b.x.x.x.c.x.x.x.d.x.x.x.e.x.x.x.f.x.x.x.a.x.x.x
aKeep: a.d
dicKeep: a.d
a 24 a.x.x.x.b.x.x.x.c.x.x.x.d.x.x.x.e.x.x.x.f.x.x.x.a.x.x.x
f 20 a.x.x.x.b.x.x.x.c.x.x.x.d.x.x.x.e.x.x.x.a.x.x.x
e 16 a.x.x.x.b.x.x.x.c.x.x.x.d.x.x.x.a.x.x.x
d 12 a.x.x.x.b.x.x.x.c.x.x.x.d.x.x.x.a.x.x.x
c 8 a.x.x.x.b.x.x.x.d.x.x.x.a.x.x.x
b 4 a.x.x.x.d.x.x.x.a.x.x.x
a 0 a.x.x.x.d.x.x.x.a.x.x.x
alSrc: a.x.x.x.d.x.x.x.a.x.x.x

As to the mystery of .Count - ?:

1 2 3 4 5 6 7 8 - Count 1 - 8
0 1 2 3 4 5 6 7 - Idx   0 - 7
A x x x B x x x - Count (8) - Step (4) = Pos to check (4)
                  Count (8) - Step + 1 (5) = Not the pos to check (3)
Ekkehard.Horner
  • 38,498
  • 2
  • 45
  • 96
  • can you just give me a tips about the Post - [Post](http://stackoverflow.com/questions/14119936/i-am-not-able-to-clear-and-reset-the-background-color-of-a-cell#comment19549322_14119936) . I tried there but looking a one liner , and I know it possible, Thus asking you to help! please – CodeLover Jan 02 '13 at 14:31
  • why `.Count-4` not `.Count-5`. As Count give us the Total number of elements, and to access that element we used always ArrayList(Count-1). Correct me if I am wrong! – CodeLover Jan 02 '13 at 14:56
  • Thanks for your clarification!! Love your knowledge! – CodeLover Jan 02 '13 at 15:19
  • Could you just help on my above mentioned post? – CodeLover Jan 02 '13 at 15:20
0

Resetting For loop counter means you somewhat do not let it iterate. You have to be very careful not to run into an infinite loop. Frankly not reading your huge text. But looking at your code and title, please do try the following:

For IndexSearch = 0 To ArrayListTaskDetails.Count - 1 step 4
    Counter = 0
    Do while Flag
       If VMHArray(Counter) = ArrayListTaskDetails (IndexSearch) Then
          ArrayListTaskDetails.RemoveRange IndexSearch, 4
          Flag = False
          If IndexSearch >= 4 then 
            IndexSearch = IndexSearch - 4 '-- add this to go back to previous index
          End If
       End If
       Counter = Counter + 1
    Loop
Next IndexSearch
bonCodigo
  • 14,268
  • 1
  • 48
  • 91
  • what `IndexSearch + 4` does? – CodeLover Jan 02 '13 at 14:06
  • 1
    Keep in mind that the loop will still try to iterate to the original `ArrayListTaskDetails.Count - 1` causing a subscript out of range error for `ArrayListTaskDetails (IndexSearch)`. VBScript does not update to `from` and `to` values during a loop. – AutomatedChaos Jan 02 '13 at 14:16
  • @AutomatedChaos Already warned OP about *infinity* ;) and just trying to get him understand what is happening with the code. So OP can set propert error handling, validations.. – bonCodigo Jan 02 '13 at 14:18