HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Reversing each word of a string while keeping the case index

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
casekeepingthewhileeachwordindexstringreversing

Problem

I was given a simple requirement for reversing a string. The requirement is as follows:

In any programming language, create an input that accepts "My name is Albert McDonald." and outputs the reversed value "Ym eman si Trebla DlAnodcm."

I got it to work like this:

string expectedInput = "My name is Albert McDonald.";

//Prompt the user to enter "My name is Albert McDonald."
Console.WriteLine("Please enter the sentence \"" + expectedInput + "\"");
Console.WriteLine();

//Wait for the users input.
string inputText = Console.ReadLine();

//Convert the input to a char array.
List characters = inputText.ToList();

//Get the list of uppercase indexes
List upperIndexes = new List();
for (int index = 0; index < characters.Count; index++)
{
    if (Char.IsUpper(characters[index]))
        upperIndexes.Add(index);
}

//Remove the period at the end
inputText = inputText.Substring(0, inputText.Length - 1);

//Get the reversed array of words.
string[] words = inputText.Split(' ').Reverse().ToArray();

//Join the array back to a string.
string revesedWords = string.Join(" ", words);

//Reverse the entire string and make it all lower case.
string result = new string(revesedWords.Reverse().ToArray()).ToLower();
StringBuilder sb = new StringBuilder(result);

//Change the case of the original index
foreach (int index in upperIndexes)
{
    char newCharacter = char.Parse(result.Substring(index, 1).ToUpper());
    sb[index] = newCharacter;
}

//Output the resutlt
Console.WriteLine("Your name in reverse by word is: \"" + sb.ToString() + ".\"");
Console.WriteLine();

//Inform the user how to close the screen.
Console.WriteLine("Press any key to close the screen.");
Console.ReadLine();


Is there a better way in terms of lines of code and performance-wise?

Solution

If you aim for fewer lines of code, you could of course put everything into a single line, but that would not helpful at all.

However, you could shorten your code a bit by using a simple regular expression and some linq-fu, something like:

var s = yourInputString;

// split string into words
var splitted = Regex.Split(s, @"(\W)").Select(r => r.AsEnumerable()).ToArray();

// reverse each word
var reversed = splitted.Select(sp => sp.Reverse().ToArray());

// adjust case
var zipped = splitted.Zip(reversed, (a, b) => string.Join("", a.Select((c, i) => char.IsUpper(c) ? 
                                                                                 char.ToUpper(b[i]) : 
                                                                                 char.ToLower(b[i]))));

// join back to string
var result = string.Join("", zipped);


I would not care about performance in this case, because it would be pointless.

Also, reversing a string with Reverse().ToArray() will corrupt your string if it contains surrogate characters, but this is probably out of scope of your task.

Code Snippets

var s = yourInputString;

// split string into words
var splitted = Regex.Split(s, @"(\W)").Select(r => r.AsEnumerable()).ToArray();

// reverse each word
var reversed = splitted.Select(sp => sp.Reverse().ToArray());

// adjust case
var zipped = splitted.Zip(reversed, (a, b) => string.Join("", a.Select((c, i) => char.IsUpper(c) ? 
                                                                                 char.ToUpper(b[i]) : 
                                                                                 char.ToLower(b[i]))));

// join back to string
var result = string.Join("", zipped);

Context

StackExchange Code Review Q#25335, answer score: 7

Revisions (0)

No revisions yet.