2

I am trying to code a function to reverse words in a string in c#, Ex: "This is some text, hello world"
should be printed like "world hello, text some is This" the number of white spaces must be same in reverse string and special characters like comma must be correctly placed after the preceding word as shown in reverse string. I tried following, but it is not taking care of special characters like ','

public static string reverseStr(string s)
{
    string result = "";
    string word = "";
    foreach (char c in s)
    {
        if (c == ' ')
        {
            result = word + ' ' + result;
          word= "";
        }
         else
        {
            word = word + c;
        }
    }
    result = word + ' ' + result;
    return result;


}
Braiam
  • 1
  • 11
  • 47
  • 78
dolly
  • 29
  • 3
  • 2
    you must be getting compile error, as there is no `string.empty`, it is `string.Empty` (observe **E**). – Abhishek Apr 28 '15 at 06:15
  • Well I didn't copy and paste exactly, edited now – dolly Apr 28 '15 at 06:18
  • what results (output) is that giving you? – Johan Apr 28 '15 at 06:20
  • 1
    What do you mean by "correctly" placed? Are you aware that there are multi-code sequences in unicode that should not be reversed? Reversing unicode strings is not an easy task to get right in the general case. For localized cases, like only english text and no such "oddball" unicode codepoints, it is easy. As an example, with the right characters the string `"aè"` will be reversed to `"eà"` because it actually is something like `"ae"` – Lasse V. Karlsen Apr 28 '15 at 06:35

3 Answers3

4

what do you mean

with special characters like comma

are there other characters that need to be treated different? This turns "This is some text, hello world" to your expected result "world hello, text some is This"

string input = "This is some text, hello world";
string result = string.Join(" ", input.Split(' ', ',').Reverse()).Replace("  ", ", ");

UPDATE

if you want to treat every special character, you need a RegEx Solution.

string result2 =string.Join(string.Empty,  System.Text.RegularExpressions.Regex.Split(input, @"([^\w]+)").Reverse());
fubo
  • 44,811
  • 17
  • 103
  • 137
2

Here's a solution using regex:

Regex.Replace(
        string.Join("",         //3. Join reversed elements
            Regex.Split(input, @"(\s+)|(,)")   //1. Split by space and comma, keep delimeters
                .Reverse()),    //2. Reverse splitted elements
@"(\s+),", @",$1");         //4. Fix comma position in joined string
Phuong Nguyen
  • 2,960
  • 1
  • 16
  • 25
0

The following solution keeps all whitespaces.
It first detects the kind (separator vs word/content) of any character and stores a list of chunks (where each item contains the start and end index, together with a boolean telling whether the chunk contains separators or word).
Then it writes the chunks to a result string in reversed order.

The order of characters inside each chunks is preserved, being the chunk a separator or word/content: this allow also to keep any double space or other chain of separators without need to post-check their sequence or quantity.

public static string Reverse(string text, Func<char, bool> separatorPredicate)
{
    // Get all chars from source text
    var aTextChars = text.ToCharArray();

    // Find the start and end position of every chunk
    var aChunks = new List<Tuple<int, int, bool>>();
    {
        var bLast = false;
        var ixStart = 0;
        // Loops all characters
        for (int ixChar = 0; ixChar < aTextChars.Length; ixChar++)
        {
            var ch = aTextChars[ixChar];
            // Current char is a separator?
            var bNow = separatorPredicate(ch);
            // Current char kind (separator/word) is different from previous
            if ((ixChar > 0) && (bNow != bLast))
            {
                aChunks.Add(Tuple.Create(ixStart, ixChar - 1, bLast));
                ixStart = ixChar;
                bLast = bNow;
            }
        }
        // Add remaining chars
        aChunks.Add(Tuple.Create(ixStart, aTextChars.Length - 1, bLast));
    }

    var result = new StringBuilder();
    // Loops all chunks in reverse order
    for (int ixChunk = aChunks.Count - 1; ixChunk >= 0; ixChunk--)
    {
        var chunk = aChunks[ixChunk];
        result.Append(text.Substring(chunk.Item1, chunk.Item2 - chunk.Item1 + 1));
    }

    return result.ToString();
}
public static string Reverse(string text, char[] separators)
{
    return Reverse(text, ch => Array.IndexOf(separators, ch) >= 0);
}
public static string ReverseByPunctuation(string text)
{
    return Reverse(text, new[] { ' ', '\t', '.', ',', ';', ':' });
}
public static string ReverseWords(string text)
{
    return Reverse(text, ch => !char.IsLetterOrDigit(ch));
}

There are 4 methods:

  • Reverse(string text, Func separatorPredicate) receives the source text and a delegate to determine when a character is a separator.
  • Reverse(string text, char[] separators) receives the source text and an array of chars to be treated as separators (any other char is word/content).
  • ReverseByPunctuation(string text) receives only the source text and delegates the computation to the first overload passing a predefined set of separator chars.
  • ReverseWords(string text) receives only the source text and delegates the computation to the first overload passing a delegate that recognize as separator everything that is not a letter or digit.
Rubidium 37
  • 661
  • 6
  • 12