Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Problem while removing items of an arraylisth through a for loop 1

Status
Not open for further replies.

WomanPro

Programmer
Nov 1, 2012
180
GR
I am trying via the following code to remove from the list all the values are equal to zero. However I am facing a strange proble. While I was running it step by step, the count of list decreases according to the item I remove each time. Fine up to here. I really don't understand a thing I am getting error because i is out of range. I am saying for i=0 to lst.count-1
the lst.count changes each time I remove an item. I don't understand how is it possible i=4 to access the loop :/ Could anyone explain me, what's going on here?

Dim lst As New ArrayList
lst.Add(5)
lst.Add(4)
lst.Add(0)
lst.Add(2)
lst.Add(0)
lst.Add(8)
Dim i As Integer
For i = 0 To lst.Count - 1
If lst(i) = 0 Then
lst.RemoveAt(lst(i))
End If
Next



However I know that the right code to do that is, but I really dont' understand, why it doesn't work with the previous way.
Any help will be much appreciated. Thank you so much in advanced.
Dim number As Integer
For Each number In lst
If number = 0 Then
lst.Remove(number)
End If
Next


 
a) The moment you remove an item from the list, you change its .Count! ;-)

==>Cycle backwards through the list and you're safe:
Code:
For i = lst.Count-1 to 0 Step - 1

b) Not sure whether VB.Net is 0 based. You might have to do this:
Code:
For i=lst.Count to 1 Step - 1

Good luck!
MakeItSo


“Knowledge is power. Information is liberating. Education is the premise of progress, in every society, in every family.” (Kofi Annan)
Oppose SOPA, PIPA, ACTA; measures to curb freedom of information under whatever name whatsoever.
 
Thank you MakeItSo

It worked in that way ;)
i = lst.Count - 1
For i = i To 0 Step -1
If lst(i) = 0 Then
lst.Remove(lst(i))
i = lst.Count
End If
Next

Question: I know that every time I remove an item list changes its count!!!
And I tried this with no effect
i = 0
cnt = lst.Count - 1
For i = i To cnt
If lst(i) = 0 Then
lst.Remove(lst(i))
cnt = lst.Count - 1
i = i - 1
End If
Next
So, in my code when i=2 the item is removed, cnt=4, i=1
next i, i=2 next i, i=3
the item is removed, cnt=3, i=2
next i, i=3 next i, i=4... error (it shouldn't access the loop inside because i=4 cnt=3 i>cnt)
It really sees that i>cnt that's why I asked why does this happen. I can't understand it. It shouldn't happen. I just don't understand why it acts in that way :/
 
i=...
For i = i To...
i=...
Next

Who in the world taught you such coding style?? It defies the logic behind i as loop counter variable - and makes your code confusing as hell!
K.I.S.S. - Keep it simple and stupid.

Say the list has 6 items (0...5).
Say you start at 6th item (item(5)) and remove it. The list now has only 5 items (0..4), by using "Step-1" your i counter now has value 4, you check 5th item (item(4)) - and do not have to worry that item(5) no longer exists! All your "i=..." statements serve absolutely no purpose save to cause confusion.

i = 0
cnt = lst.Count - 1
cnt = lst.Count - 1
i = i - 1


Now look at these three lines:
Code:
For i = lst.Count - 1 To 0 Step -1
[indent]If lst(i) = 0 Then lst.RemoveAt(lst(i))[/indent]
Next i

They do exactly what you need, you do not have to reset variable values at all.
See?

Cheers,
MakeItSo

“Knowledge is power. Information is liberating. Education is the premise of progress, in every society, in every family.” (Kofi Annan)
Oppose SOPA, PIPA, ACTA; measures to curb freedom of information under whatever name whatsoever.
 
COrrection:
You need 4 lines, you must keep this:
Code:
cnt = lst.Count - 1
For i = cnt to 0 Step -1
...

“Knowledge is power. Information is liberating. Education is the premise of progress, in every society, in every family.” (Kofi Annan)
Oppose SOPA, PIPA, ACTA; measures to curb freedom of information under whatever name whatsoever.
 
Thank you so much MakeItSo, I understand your way, I know that it can work in other ways too, as for example with
While i < lst.Count - 1
If lst(i) = 0 Then lst.Remove(lst(i)) Else : i += 1
End While

The reason I run step over many times is that it helps me to find errors in a big ammount of codes in specific items when I can't find what's wrong. I really have learn this since I was study in my school!!! It's somehow a safe way in some cases for me. I also like to have alternative ways to do something and to understand why one way of code doesn't work, because it's very easy to make again and again the same mistake when I haven't understand why it didn't work. And sometimes we get in trouble for nothing. Thank you so much for the solution but except that, I need somebody to explain me why in my way it didn't work
It's the same thing if I replayce cnt with lst.count-1, the same effect remains.

For i = i To lst.Count - 1
If lst(i) = 0 Then
lst.Remove(lst(i))
i = i - 1
End If
Next i

The list count decreases by 1 everytime I remove an item so it shouldn't pass the line for i=i to lst.count-1
because i>lst.count-1 that's why the error occurs. I don't understand why compiler pass a false statement. That's I asked about it, and if you see my initial post I gave and another solution too, of what I want to do, I just need to understand the reason that compiler access the line for i=i to lst.count-1 while i>list.count-1.
 
I have always find it most useful to set breakpoints, single-step through loops and either use inpection or simply hover my cursor over variables to see their current value.
The trouble with lst.Count is that when you remove an item, you alter the list, so lst.Count will be reduced, hence you get basically a double effect: you alter your counter variable, i, and additionally your upper(lower) bound, lst.Count.
That's why I wrote:
you must keep this:
cnt = lst.Count - 1
For i = cnt to 0 Step -1

By using the variable cnt, you secure the original value of lst.Count which means that your loop will always rund exactly original lst.Count times, i.e. 4 times for 4 original items.
That being said, I suspect your code contains another error:
Code:
lst.RemoveAt(lst(i))
RemoveAt expects an index, not a list item!
So your code should actually look more like this:
Code:
cnt = lst.Count - 1
For i = cnt to 0 Step -1
  If lst(i) = 0 Then lst.[COLOR=#CC0000]RemoveAt(i)[/color]
Next i

Does that help?

Cheers,
MakeItSo

“Knowledge is power. Information is liberating. Education is the premise of progress, in every society, in every family.” (Kofi Annan)
Oppose SOPA, PIPA, ACTA; measures to curb freedom of information under whatever name whatsoever.
 
Somehow yes thank you. Maybe it's what you say, the compiler doesn't recognize the ubound of the array because it changes many times, it is like a fake recognizion of the lst.Count value. Anyway thank you!!!!!!! I just found it so strange!!!!!!
 

Its Remove not RemoveAt method ;)
lst.Remove(lst(i))
 
Oh yes, I completely missed that you changed that! :)

==> RemoveAt would be safer since the index is distinct but the item value may not be.
If you remove "0" from list, it will remove the first item with that value which is not necessarily the one at the position you just checked.


“Knowledge is power. Information is liberating. Education is the premise of progress, in every society, in every family.” (Kofi Annan)
Oppose SOPA, PIPA, ACTA; measures to curb freedom of information under whatever name whatsoever.
 
[bigcheeks]
Glad you got it sorted.
[thumbsup2]

“Knowledge is power. Information is liberating. Education is the premise of progress, in every society, in every family.” (Kofi Annan)
Oppose SOPA, PIPA, ACTA; measures to curb freedom of information under whatever name whatsoever.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top