For Each Loop Iteration Count - vb.net

Can we keep track of our iteration in our loop when we use a For Each? I like to use the For Each loops for looping through my objects but I cannot seem to find a way to keep an index of where I'm at in the loop. Unless of course I create my own ...

If you want to have an index, use a For-loop instead of a For each. That's why it exists.
For i As Int32 = 0 To objects.Count - 1
Dim obj = objects(i)
Next
Of course nothing prevents you from creating your own counter:
Dim counter As Int32 = 0
For Each obj In objects
counter += 1
Next
or you can use Linq:
Dim query = objects.Select(Function(obj, index) "Index is:" & index)

There's no built-in solution yet. Of course you know how to do it with a counter but this maybe what you are looking for (By Jon Skeet)

You can do it like this:
Dim index as integer = 0
For Each item in list
'do stuff
index += 1
Next
Off course, depending on the collection your iterating over, there is no guaranteeing that item will be the same as list.item(index), but wether or not that matters depends on what you are doing.
For index as integer = 0 to list.count - 1
Dim item = list.item(index)
'do stuff
Next
That is the other alternative if you need item to be the same as list.item(index).

Related

Transferring items from one listBox to another list

i have ListBox1 and ListBox2 and textbox
I want the following when setting a value in a TextBox. If the value in ListBox is1, then items are moved from the current value to the last items in not the first. to listbox2
Dim foo As String
Dim index As Integer = 0
Dim good As Integer = 0
foo = TextBox1.Text
ListBox2.Items.Clear()
For i = 0 To ListBox1.Items.Count - 1
If ListBox1.Items(i).ToString = foo Then
index = i
End If
If i >= index Then
ListBox2.Items.Add(ListBox1.Items(good).ToString)
End If
Next
As Lars has noted in a comment, the index is 0 at the beginning so the condition i >= index wil be always true. So you need to intialize it with Int32.MaxValue.
You add always the first item, because good is always 0. You should use the loop variable i:
ListBox2.Items.Add(ListBox1.Items(i).ToString())
Here is a LINQ version which simplifies the whole code, you don't need more:
ListBox2.Items.Clear()
Dim allAfter = ListBox1.Items.Cast(Of Object).SkipWhile(Function(item) Not TextBox1.Text.Equals(item))
ListBox2.Items.AddRange(allAfter.ToArray())

Get row index if some column value is equal to something

In this datatable there are no duplicates, I need the row index where column x value equals 2. I would do it like this:
Dim rowIndex As Integer = 0
For i = 0 To mtable.Rows.Count - 1
If mtable.Rows(i)("x") = 2 Then
rowIndex = i
Exit For
End If
Next
I will be calling this process multiple times per second. Is there a faster way to do this in .NET?
DataTable select could work, i think it should be faster than iterating over the collection of rows.
var index = mtable.Rows.IndexOf(mtable.Select("x = 2").FirstOrDefault());
Multiple times per second is a bit vague - tens or thousands?
You could create a hash table mapping the value of "x" to the row number:
Dim nLookups = mtable.Rows.Count - 1
Dim lookupHash As New Hashtable(nLookups)
For i = 0 To nLookups
lookupHash.Add(CInt(mtable.Rows(i)("x")), i)
Next
then
Dim rowSought As Integer = -1
If lookupHash.ContainsKey(2) Then
rowSought = lookupHash(2)
End If
Or if the range of possible values of "x" is suitable, you could use an array to map the value to the row number.

Return the previous index in vb.net?

I have a For Each loop that is looping through an array of strings to find the first string with a length of three characters. For example, when looping through the array, if the first 3 character string is the 4th index of the array, I would like for it to return the 3rd (previous) index of the array. Any help would be appreciated.
For Each piece As String In p
If piece.Length = 3 Then
'Return previous index
End If
Next
You have a couple of options.
If p is a collection accessible by index (ie: IList(Of T)), you can switch to a For loop, and return the element at the current index -1.
Otherwise, you can keep the previous item in a separate variable, and return it when your condition is met.
Dim lastItem as String
For Each piece As String In p
If piece.Length = 3 Then
Return lastItem ' Will return Nothing if this is the first item...
End If
lastItem = piece ' Store this for next time
Next
How about something like this:
For i As Integer = 1 To p.Count - 1
If p(i).Length = 3 Then
'Return previous index
Return p(i - 1)
End If
Next
Note the loop will have to start at 1 (not zero) otherwise you could return the (0-1)th element of the array which won't exist
I would use .FindIndex, if you have a List(Of T):
Dim i As Integer = p.FindIndex(Function(x) x.Length = 3)
If i > 0 Then
Dim previous As String = p(i - 1)
'Do something
End If
If you have a String(), you can also use the Array version:
Array.FindIndex(Of String)(p, Function(x) x.Length = 3)

Not able to add values in second Combobox

Here is my code.
for example TextBox1.Text= 12,34,45,67,67
Dim process_string As String() = TextBox1.Text.Split(New Char() {","})
Dim process As Integer
For Each process In process_string
Combo1.Items.Add(process)
count = count + 1
Next process
total_process.Text = count
End If
Dim array(count) As String
Dim a As Integer
For a = 0 To count - 1
array(a) = Combo1.Items(a).ToString
Next
a = 0
For a = count To 0
Combo2.Items.Add(array(a).ToString)
Next
i want to add values in reversed order in combobox2 that are available in combobox1
but when i run the application the second combobox remains empty and not showing any value.
You've specified this for loop
For a = count To 0
But you need to add STEP -1 to go backwards like that.
For a = count To 0 Step -1
2 things. First of all, K.I.S.S. Keep it simple stupid
For i As Integer = ComboBox1.Items.Count - 1 To 0 Step -1
ComboBox2.Items.Add(ComboBox1.Items(i))
Next
second: It didn't work because you forgot the Step -1 on your last loop
~~~~~~~~~~~~~~Edit~~~~~~~~~~~~~~
Sorting the data in a combo box should be done with the sorted property on a combo box
ComboBox3.Sorted = True
Sorting the data in reverse order should be done with arrays as you were trying to do before. The following code should suffice:
Dim List As ArrayList = ArrayList.Adapter(ComboBox3.Items)
List.Sort()
List.Reverse()
ComboBox4.Items.AddRange(List.ToArray)
If you wanted to get creative, you could potentially create your own combo box class and make your own version of the sorted property that allows for "sort alpha", "sort numeric", "sort alpha Desc", and "sort numeric desc" and perhaps some other options. But I'd only do that if you were going to use this in a lot of places.

vb.net: index number in "for each"

Sometime in VB.net i have something like:
For Each El in Collection
Write(El)
Next
But if i need the index number, i have to change it to
For I = 0 To Collection.Count() - 1
Write(I & " = " & Collection(I))
Next
Or even (worse)
I = 0
For Each El In Collection
Write(I & " = " & El)
I += 1
Next
Is there another way of getting the index?
If you are using a generic collection (Collection(of T)) then you can use the IndexOf method.
For Each El in Collection
Write(Collection.IndexOf(El) & " = " & El)
Next
I believe your original way of doing it with a counter variable is the most efficient way of doing it. Using Linq or IndexOf would kill the performance.
Dim i as Integer = 0
For Each obj In myList
'Do stuff
i+=1
Next
If you need the index then a for loop is the most straightforward option and has great performance. Apart from the alternatives you mentioned, you could use the overloaded Select method to keep track of the indices and continue using the foreach loop.
Dim list = Enumerable.Range(1, 10).Reverse() ''# sample list
Dim query = list.Select(Function(item, index) _
New With { .Index = index, .Item = item })
For Each obj In query
Console.WriteLine("Index: {0} -- Item: {1}", obj.Index, obj.Item)
Next
However, I would stick to the for loop if the only reason is to iterate over it and know the index. The above doesn't make it clear why you chose to skip the for loop.
If you need the index, change the way you iterate through the collection:
You have already come up with the simplest answer:
For i = 0 To Collection.Count() - 1
DoStuffWith(Collection(i))
Next