MazoKisto MazoKisto - 6 months ago 18
Vb.net Question

For Loop: changing the loop condition while it is looping

What I want to do is replace all 'A' in a string with "Bb". but it will only loop with the original string not on the new string.

for example:

AAA

BbAA

BbBbA

and it stops there because the original string only has a length of 3. it reads only up to the 3rd index and not the rest.

Dim txt As String
txt = output_text.Text

Dim a As String = a_equi.Text

Dim index As Integer = txt.Length - 1
Dim output As String = ""

For i = 0 To index
If (txt(i) = TextBox1.Text) Then
output = txt.Remove(i, 1).Insert(i, a)
txt = output
TextBox2.Text += txt + Environment.NewLine

End If
Next
End Sub

Answer

I think this leaves us looking for a String.ReplaceFirst function. Since there isn't one, we can just write that function. Then the code that calls it becomes much more readable because it's quickly apparent what it's doing (from the name of the function.)

Public Function ReplaceFirst(searched As String, target As String, replacement As String) As String

    'This input validation is just for completeness.
    'It's not strictly necessary.

    'If the searched string is "null", throw an exception.
    If (searched Is Nothing) Then Throw New ArgumentNullException("searched")

    'If the target string is "null", throw an exception.
    If (target Is Nothing) Then Throw New ArgumentNullException("target")

    'If the searched string doesn't contain the target string at all
    'then just return it - were done.
    Dim foundIndex As Integer = searched.IndexOf(target)
    If (foundIndex = -1) Then Return searched

    'Build a new string that replaces the target with the replacement.
    Return String.Concat(searched.Substring(0, foundIndex), replacement, _
        searched.Substring(foundIndex + target.Length, searched.Length - (foundIndex + target.Length)))
End Function

Notice how when you read the code below, you don't even have to spend a moment trying to figure out what it's doing. It's readable. While the input string contains "A", replace the first "A" with "Bb".

Dim input as string = "AAA"
While input.IndexOf("A") > -1
   input = input.ReplaceFirst(input,"A","Bb")
   'If you need to capture individual values of "input" as it changes
   'add them to a list.
End While

You could optimize or completely replace the function. What matters is that your code is readable, someone can tell what it's doing, and the ReplaceFirst function is testable.

Then, let's say you wanted another function that gave you all of the "versions" of your input string as the target string is replaced:

Public Function GetIterativeReplacements(searched As String, target As String, replacement As String) As List(of string)
    Dim output As New List(Of String)
    While searched.IndexOf(target) > -1
        searched = ReplaceFirst(searched, target, replacement)
        output.Add(searched)
    End While
    Return output
End Function

If you call

dim output as List(of string) = GetIterativeReplacments("AAAA","A","Bb")

It's going to return a list of strings containing

BbAAA, BbBbAA, BbBbBbA, BbBbBbBb

It's almost always good to keep methods short. If they start to get too long, just break them into smaller methods with clear names. That way you're not trying to read and follow and test one big, long function. That's difficult whether or not you're a new programmer. The trick isn't being able to create long, complex functions that we understand because we wrote them - it's creating small, simpler functions that anyone can understand.