Dre
Dre

Reputation: 3

Put a space in front of every capital letter in a string

I want to put spaces before each capital letter in a string.

So turn this: TheQuickBrownFox

into this: The Quick Brown Fox

This is the code I have so far: it finds uppercase chars in the string and shows each upper letter in a Message Box.
I can't figure out where to go from here:

Dim input As String = "TheQuickBrownFox"

For i As Integer = 0 To input.Length - 1
    Dim c As Char = input(i)

    If Char.IsUpper(c) Then
        MsgBox(c)
    End If
Next

I've googled around but I wasn't able to find a solution for visual basic.

Upvotes: 0

Views: 362

Answers (4)

Jimi
Jimi

Reputation: 32233

A couple of example using LINQ:

Imports System.Linq
Imports System.Text

Dim input As String = "TheQuickBrownFox"
  • In case you don't know it, a String is a collection of Chars, so you can iterate the string content using a ForEach loop (e.g., For Each c As Char In input).

▶ Generate a string from an collection of chars (Enumerable(Of Char)), excluding the first uppercase char if it's the first in the string.
The second parameter of a Select() method, when specified (in Select(Function(c, i) ...)), represents the index of the element currently processed.
String.Concat() rebuilds a string from the Enumerable(Of Char) that the Select() method generates:

Dim result = String.Concat(input.Select(Function(c, i) If(i > 0 AndAlso Char.IsUpper(c), ChrW(32) + c, c)))

The same, not considering the position of the first uppercase char:

Dim result = String.Concat(input.Select(Function(c) If(Char.IsUpper(c), ChrW(32) + c, c)))

▶ With an aggregation function that uses a StringBuilder as accumulator (still considering the position of the first uppercase char).

When processing strings, a StringBuilder used as storage can make the code more efficient (creates way less garbage) and more performant.
See, e.g., here: How come for loops in C# are so slow when concatenating strings?

➨ Note that I'm adding an Array of chars to the StringBuilder:

Dim result = input.Aggregate(New StringBuilder(), 
    Function(sb, c) sb.Append(If(sb.Length > 0 AndAlso Char.IsUpper(c), {ChrW(32), c}, {c})))

result is a StringBuilder object: extract the string with result.ToString().

Or, as before, without considering the position:

Dim result = input.Aggregate(New StringBuilder(), 
    Function(sb, c) sb.Append(If(Char.IsUpper(c), {ChrW(32), c}, {c})))

▶ The two example above are somewhat equivalent to a simple loop that iterates all chars in the string and either creates a new string or uses a StringBuilder as storage:

Dim sb As New StringBuilder()
For Each c As Char In input
    sb.Append(If(sb.Length > 0 AndAlso Char.IsUpper(c), {ChrW(32), c}, {c}))
Next

Change the code as described before if you want to add a space to the first uppercase Char without considering its position.

Upvotes: 2

Slugsie
Slugsie

Reputation: 905

To expand on your code:

Dim input As String = "TheQuickBrownFox"
Dim outputSB as new StringBuilder

For i As Integer = 0 To input.Length - 1
    Dim c As Char = input(i)

    If Char.IsUpper(c) Then
        outputSB.Append(" ")
        'MsgBox(c)
    End If

    outputSB.Append(c)
Next

Console.Writeline(outputSB.ToString())

Upvotes: 0

Karen Payne
Karen Payne

Reputation: 5127

Yet another option is a language extension method.

Imports System.Text.RegularExpressions

Module Module1

    Sub Main()
        Demo()
        Console.ReadLine()
    End Sub

    Private Sub Demo()
        Dim data = New List(Of String) From
                {
                "ThisIsASentence",
                "TheQuickBrownFox",
                "ApplesOrangesGrapes"}

        data.ForEach(Sub(item) Console.WriteLine($"{item,-25}[{item.SplitCamelCase}]"))
    End Sub

End Module
Public Module StringExtensions
    <Runtime.CompilerServices.Extension>
    Public Function SplitCamelCase(sender As String) As String

        Return Regex.Replace(Regex.Replace(sender,
        "(\P{Ll})(\P{Ll}\p{Ll})", "$1 $2"),
                             "(\p{Ll})(\P{Ll})",
                             "$1 $2")
    End Function

End Module

enter image description here

Upvotes: 2

Caius Jard
Caius Jard

Reputation: 74625

You can use a regular expression:

Dim input = "TheQuickBrownFox"
Dim withSpaces = Regex.Replace(a, "(?<!^)([A-Z])", " $1")

The regex finds any uppercase A-Z that are not preceded by the start of the string and captures it into a group. The replacement takes the group content and prefixes a space

If you don't want to use the negative lookbehind, you can trim the result:

Dim withSpaces = Regex.Replace(a, "([A-Z])", " $1").TrimStart()

Or don't trim if you don't care that the string starts with a space

Upvotes: 1

Related Questions