Marshall Marshall - 4 months ago 14
C# Question

How to deal with reversing an array when we do not want to change the position of special characters

I'm working on reversing a sentence. I'm able to do it. But I'm not sure, how to reverse the word without changing the special characters positions. I'm using regex but as soon as it finds the special characters it's stopping the reversal of the word.

Following is the code:

Console.WriteLine("Enter:");
string w = Console.ReadLine();
string rw = String.Empty;
String[] arr = w.Split(' ');
var regexItem = new Regex("^[a-zA-Z0-9]*$");
StringBuilder appendString = new StringBuilder();
for (int i = 0; i < arr.Length; i++)
{
char[] chararray = arr[i].ToCharArray();
for (int j = chararray.Length - 1; j >= 0; j--)
{

if (regexItem.IsMatch(rw))
{
rw = appendString.Append(chararray[j]).ToString();
}
}
sb.Append(' ');
}
Console.WriteLine(rw);
Console.ReadLine();


Example : Input


Marshall! Hello.


Expected output


llahsram! olleh.

Answer Source

A basic solution with regex and LINQ. Try it online.

public static void Main()
{
    Console.WriteLine("Marshall! Hello.");
    Console.WriteLine(Reverse("Marshall! Hello."));
}

public static string Reverse(string source)
{
    // we split by groups to keep delimiters
    var parts = Regex.Split(source, @"([^a-zA-Z0-9])");
    // if we got a group of valid characters
    var results = parts.Select(x => x.All(char.IsLetterOrDigit)
            // we reverse it
            ? new string(x.Reverse().ToArray())
            // or we keep the delimiters as it
            : x);
    // then we concat all of them
    return string.Concat(results);
}

The same solution without LINQ. Try it online.

public static void Main()
{
    Console.WriteLine("Marshall! Hello.");
    Console.WriteLine(Reverse("Marshall! Hello."));

}

public static bool IsLettersOrDigits(string s)
{
    foreach (var c in s)
    {
        if (!char.IsLetterOrDigit(c))
        {
            return false;
        }
    }
    return true;
}

public static string Reverse(char[] s)
{
    Array.Reverse(s);
    return new string(s);
}


public static string Reverse(string source)
{
    var parts = Regex.Split(source, @"([^a-zA-Z0-9])");

    var results = new List<string>();
    foreach(var x in parts)
    {
        results.Add(IsLettersOrDigits(x)
                   ? Reverse(x.ToCharArray())
                   : x);
    }
    return string.Concat(results);
}