15

Not that I would want to use this practically (for many reasons) but out of strict curiousity I would like to know if there is a way to reverse order a string using LINQ and/or LAMBDA expressions in one line of code, without utilising any framework "Reverse" methods.

e.g.

string value = "reverse me";
string reversedValue = (....);

and reversedValue will result in "em esrever"

EDIT Clearly an impractical problem/solution I know this, so don't worry it's strictly a curiosity question around the LINQ/LAMBDA construct.

Jon Seigel
  • 12,251
  • 8
  • 58
  • 92
Student for Life
  • 1,023
  • 1
  • 9
  • 18

11 Answers11

31

Well, I can do it in one very long line, even without using LINQ or a lambda:

string original = "reverse me"; char[] chars = original.ToCharArray(); char[] reversed = new char[chars.Length]; for (int i=0; i < chars.Length; i++) reversed[chars.Length-i-1] = chars[i]; string reversedValue = new string(reversed);

(Dear potential editors: do not unwrap this onto multiple lines. The whole point is that it's a single line, as per the sentence above it and the question.)

However, if I saw anyone avoiding using framework methods for the sake of it, I'd question their sanity.

Note that this doesn't use LINQ at all. A LINQ answer would be:

string reverseValue = new string(original.Reverse().ToArray());

Avoiding using Reverse, but using OrderByDescending instead:

string reverseValue = new string(original.Select((c, index) => new { c, index })
                                         .OrderByDescending(x => x.index)
                                         .Select(x => x.c)
                                         .ToArray());

Blech. I like Mehrdad's answer though. Of course, all of these are far less efficient than the straightforward approach.

Oh, and they're all wrong, too. Reversing a string is more complex than reversing the order of the code points. Consider combining characters, surrogate pairs etc...

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Crap. I had an off by one error two times before I did it right, for such an easy problem. I'd avoid my approach at all costs! – Mehrdad Afshari Jul 20 '09 at 11:11
  • 1
    I don't know if it's just me, but I don't consider it a one liner if a statement terminator ; is used and another statement appearing straight after it. – Josh Smeaton Jul 20 '09 at 12:38
  • @Josh: Given that the whole question is somewhat ridiculous IMO, I was taking it absolutely literally. Put it this way - if you went to the line number containing each statement in that code, how many different values would you get? It just shows the value in being precise. – Jon Skeet Jul 20 '09 at 12:49
  • @Jon, the question was edited to indicate "curiosity" as I wouldn't be using this idea anywhere as I know its an impractical concept. I just wanted to find a non obvious way to perform a known operation and then was thinking of sharing it with my team to see if they could figure it out, although i have now decided to scrap the idea. – Student for Life Jul 21 '09 at 00:23
  • Your last solution (with `OrderByDescending`) is wrong, you need to get rid of the added index, so you need to call `.Select(x => x.c)` before the final `ToArray`. – Mormegil Mar 15 '13 at 09:28
  • Or just `string.Concat(input.Select((c, index) => input[input.Length - index - 1]))` – nawfal Jan 04 '14 at 01:25
  • You: _Consider combining characters, surrogate pairs etc..._ Yeah, I just added an answer that tries to handle these things, with "text elements" from the `StringInfo`. – Jeppe Stig Nielsen Aug 10 '16 at 13:55
25

I don't see a practical use for this but just for the sake of fun:

new string(Enumerable.Range(1, input.Length).Select(i => input[input.Length - i]).ToArray())
Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
22
new string(value.Reverse().ToArray())
Pranay Rana
  • 175,020
  • 35
  • 237
  • 263
shlomiw
  • 221
  • 2
  • 2
7
var reversedValue = value.ToCharArray()
                         .Select(ch => ch.ToString())
                         .Aggregate<string>((xs, x) => x + xs);
Joe Chung
  • 11,955
  • 1
  • 24
  • 33
5

Variant with recursive lambda:

  var value = "reverse me";
  Func<String, String> f = null; f = s => s.Length == 1 ? s : f(s.Substring(1)) + s[0]; 
  var reverseValue = f(value);

LP, Dejan

Dejan Stanič
  • 787
  • 7
  • 14
5

You can use Aggregate to prepend each Char to the reversed string:

 "reverse me".Aggregate("", (acc, c) => c + acc);
Ben Lings
  • 28,823
  • 13
  • 72
  • 81
2

In addition to one previous post here is a more performant solution.

var actual0 = "reverse me".Aggregate(new StringBuilder(), (x, y) => x.Insert(0, y)).ToString();
The Void
  • 21
  • 2
2
var reversedValue= "reverse me".Reverse().ToArray();
rsa
  • 329
  • 2
  • 5
1
public static string Reverse(string word)
{
   int index = word.Length - 1;
   string reversal = "";

   //for each char in word
   for (int i = index; index >= 0; index--)
   {
       reversal = reversal + (word.Substring(index, 1));
       Console.WriteLine(reversal);
   }
   return reversal;
}

Quite simple. So, from this point on, I have a single method that reverses a string, that doesn't use any built-in Reverse functions.

So in your main method, just go,

Console.WriteLine(Reverse("Some word"));

Technically that's your one liner :P

Vishav Premlall
  • 456
  • 6
  • 22
1

If we need to support combining characters and surrogate pairs:

// This method tries to handle:
// (1) Combining characters
// These are two or more Unicode characters that are combined into one glyph.
// For example, try reversing "Not nai\u0308ve.". The diaresis (¨) should stay over the i, not move to the v.
// (2) Surrogate pairs
// These are Unicode characters whose code points exceed U+FFFF (so are not in "plane 0").
// To be represented with 16-bit 'char' values (which are really UTF-16 code units), one character needs *two* char values, a so-called surrogate pair.
// For example, try "The sphere \U0001D54A and the torus \U0001D54B.". The  and the  should be preserved, not corrupted.

var value = "reverse me"; // or "Not nai\u0308ve.", or "The sphere \U0001D54A and the torus \U0001D54B.". 

var list = new List<string>(value.Length);

var enumerator = StringInfo.GetTextElementEnumerator(value);
while (enumerator.MoveNext())
{
  list.Add(enumerator.GetTextElement());
}
list.Reverse();

var result = string.Concat(list);

Documentation: MSDN: System.Globalization.StringInfo Class

Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
-2
string str="a and b";
string t="";

char[] schar = str.Reverse().ToArray();

foreach (char c in schar )
{
    test += c.ToString();
}
Jaco
  • 923
  • 2
  • 14
  • 28
  • 3
    Ten answers given and you need to add another one? Apart from that, something that always applies to code-only answers is: give a brief explanation. Finally, the question clearly states *without utilising any framework "Reverse" methods*. – Gert Arnold Nov 28 '17 at 19:16