Thalecress Thalecress - 6 months ago 12
Vb.net Question

How do I add spaces to a numeric string every 2 numbers in VB.NET?

CONCLUSION: I used a regular expression, which handles both numbers and letters in strings of arbitrary length, in one line of code.

dim rtn as String = Regex.Replace(input, "..", "$& ")


I'd like to take numeric strings of arbitrary length and insert a space every 2 characters.
So 1233456 becomes 12 33 45 6.

Is there a way I can use format as string or IFormatProvider, like? That would put a limit on how long the string could be though, right? Since I'm casting to a long.

CLng((input)).ToString("## ")


EDIT - here's the original question.
I'd like to take strings of arbitrary length and insert a space every 2 characters.
123dssas4rr should become 12 3d ss as 4r r

I was clumsily using

Dim rtn As String = String.Empty

Dim i As Integer = 0
For Each a In input.ToCharArray
rtn = String.Concat(rtn, a)
i = i + 1
If i Mod 2 = 0 Then
rtn = String.Concat(rtn, " ")
End If
Next

Answer

Maybe not the prettiest but a simple and fast approach is the plain old StringBuilder:

Const charNumber = 2
Dim oldString = "123dssas4rr"
Dim sb As New System.Text.StringBuilder()
For i As Integer = 0 To input.Length - 1
    If i Mod charNumber = 0 Then
        sb.Append(" "c)
    End If
    sb.Append(input(i))
Next
Dim newString = sb.ToString()

Edit:

Compared the StringBuilder with the Regex approach just for interest:

Dim timer As New Stopwatch
Dim regexTime As TimeSpan, stringBuilderTime As TimeSpan
Dim input As String = "123dssas4rr"
Dim result As String

timer.Start()
For i As Int32 = 1 To 10000000
    result = Regex.Replace(input, "..(?=.)", "$& ")
Next
timer.Stop()
regexTime = timer.Elapsed

timer.Restart()
Const charNumber = 2
For i As Int32 = 1 To 10000000
    Dim sb As New System.Text.StringBuilder()
    For chr As Integer = 0 To input.Length - 1
        If chr Mod charNumber = 0 Then
            sb.Append(" "c)
        End If
        sb.Append(input(chr))
    Next
    result = sb.ToString()
Next
timer.Stop()
stringBuilderTime = timer.Elapsed

Result:

Regex:           00:00:40.8928958
StringBuilder:   00:00:03.3468080

StringBuilder is 12 times faster on 10 millionen iterations even though it creates a new StringBuilder object on every iteration. The difference will be the greater, the longer the string is. Sometimes shorter solutions are not faster, same would apply to a LINQ approach.

Even if this test was not really practically relevant, if i change it to read a string from a file with 500.000 chars(500kb)and iterate 100 times, the result is even better for StringBuilder:

Regex:           00:00:15.8409331
StringBuilder:   00:00:00.8262289

StringBuilder approach is nearly 20 times faster.

Here is an extension version:

Public Module StringExtensions
    <Runtime.CompilerServices.Extension()>
    Public Function InsertStringRepeatedly(ByVal input As String, ByVal separator As String, ByVal length As Int32) As String
        Dim sb As New System.Text.StringBuilder()
        For chr As Integer = 0 To input.Length - 1
            If chr Mod length = 0 Then
                sb.Append(separator)
            End If
            sb.Append(input(chr))
        Next
        Return sb.ToString()
    End Function
End Module

You can call it in following way:

Dim result = input.InsertStringRepeatedly(" ", 2)