13
  static void Main(string[] args)
  {
     string s = "ABCDEFGH";
     string newS = ShiftString(s);
     Console.WriteLine(newS);
  }
  public static string ShiftString(string t)
  {
     char[] c = t.ToCharArray();
     char save = c[0];
     for (int i = 0; i < c.Length; i++)
     {
        if (c[i] != c[0])
        c[i] = c[i - 1];
     }
     Console.WriteLine(c);
     String s = new string(c);
     return s;
  }

I need to shift the string s one space to the left, so i end up with the string: "BCDEFGHA" So i thought about changing the string into a char array and work my way from there, but im not sure how to succesfully make this work. I'm pretty certain i need a for loop, but i need some help on how to shift the char sequence one space to the left.

user2104751
  • 149
  • 1
  • 1
  • 6

11 Answers11

16

how about this?

public static string ShiftString(string t)
{
    return t.Substring(1, t.Length - 1) + t.Substring(0, 1); 
} 
John Woo
  • 258,903
  • 69
  • 498
  • 492
  • Thanks, that seemed to work, but i'm not 100% sure how this actually works. Would be kind to explain why it does? – user2104751 Feb 24 '13 at 16:21
  • Imagine you have this string `ABC`. this part `t.Substring(1, t.Length - 1)` will yield `BC` while this one `t.Substring(0, 1)` will return `A`. – John Woo Feb 24 '13 at 16:23
  • 2
    Oh wait, i may know. The t.Substring(1, t.Length - 1) translated to "BCDEFGH" and t.Substring(0, 1) translated to "A", and by concatenating these we get "BCDEFGHA"? – user2104751 Feb 24 '13 at 16:24
12

You can try this:

s = s.Remove(0, 1) + s.Substring(0, 1);

As an extension method:

public static class MyExtensions
{
    public static string Shift(this string s, int count)
    {
        return s.Remove(0, count) + s.Substring(0, count);
    }
}

Then you can use:

s = s.Shift(1);
Alina B.
  • 1,256
  • 8
  • 18
9

The algorithm to solve this type of problem about shift n positions is duplicate the string, concatenate together and get the substring. ( n < length(string) )

string s = "ABCDEFGH";
string ss = s + s; // "ABCDEFGHABCDEFGH"

if you want to shift n position, you can do

var result = ss.Substring(n, s.length);
zs2020
  • 53,766
  • 29
  • 154
  • 219
5

In C# 8 and above...

Rotate Right by one...

t = myString[^1] + myString[..^1];

Or, Rotate Left by one...

t = myString[1..] + myString[0];

Or, Rotate Right by an amount...

t = myString[^amount..] + myString[..^amount];

Or, Rotate Left by an amount...

t = myString[amount..] + myString[..amount];
SunsetQuest
  • 8,041
  • 2
  • 47
  • 42
3

Personally I'd do this:

public static string ShiftString(string t){
    string firstLetter = t.Substring(0, 1);

    return t.Substring(1) + firstLetter;
}
Grant Clements
  • 984
  • 6
  • 14
2

You can take advantage of the fact that string is IEnumerable<char>:

public static string ShiftString(string t){
    return new String(t.Skip(1).Concat(t).Take(t.Length).ToArray());
}
driis
  • 161,458
  • 45
  • 265
  • 341
2

Using Span<T> we can significantly improve the performance. E.g.:

public static class StringExtensions
{
    public static string ShiftString(this string s)
    {
        return string.Concat(s.AsSpan(1), s.AsSpan(0, 1));
    }
}

Benchmark

This answer + existing answers. Using spans, the shifting of the string becomes both faster and produces less garbage.

|  Method |     Data |     Mean |   Median | Allocated |
|-------- |--------- |---------:|---------:|----------:|
|    L33t | ABCDEFGH | 18.56 ns | 18.21 ns |      40 B |
|  Zs2020 | ABCDEFGH | 36.04 ns | 35.20 ns |      96 B |
| JohnWoo | ABCDEFGH | 47.69 ns | 47.39 ns |     104 B |
|  AlinaB | ABCDEFGH | 52.56 ns | 52.07 ns |     104 B |

Full test code

using System;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Diagnostics.Windows;
using BenchmarkDotNet.Running;

namespace ConsoleApp10
{
    class Program
    {
        static void Main(string[] args)
        {
            var summary = BenchmarkRunner.Run<StringShiftTest>();
        }
    }

    [Config(typeof(Config))]
    public class StringShiftTest
    {
        private class Config : ManualConfig
        {
            public Config() => AddDiagnoser(MemoryDiagnoser.Default, new EtwProfiler());
        }

        [Params("ABCDEFGH")]
        public string Data;

        [Benchmark]
        public string L33t() => string.Concat(Data.AsSpan(1), Data.AsSpan(0, 1));

        [Benchmark]
        public string Zs2020() => (Data + Data).Substring(1, Data.Length);

        [Benchmark]
        public string JohnWoo() => Data.Substring(1, Data.Length - 1) + Data.Substring(0, 1);

        [Benchmark]
        public string AlinaB() => Data.Remove(0, 1) + Data.Substring(0, 1);
    }
}
l33t
  • 18,692
  • 16
  • 103
  • 180
1

The StringBuilder class give you better performance

static string ShiftString(string str)
{
    if (str == null) throw new ArgumentNullException();
    int strLen = str.Length;
    if (strLen == 0) return string.Empty;
    StringBuilder sb = new StringBuilder(strLen);
    sb.Append(str, 1, strLen - 1);
    sb.Append(str[0]);
    return sb.ToString();
}
Maksym Anurin
  • 3,167
  • 1
  • 18
  • 13
1

Below methods take the number n which tells how many times you want to shift/rotate the string. I have taken the MOD by length of string if the number is greater than the length of string.

public static void Rotate(ref string str, int n)
    {
        //if the rotation/shift number is less than or =0 throw exception
        if (n < 1)
            throw new Exception("Negative number for rotation"); 
        //if the String is less than 1 character no need to shift
        if (str.Length < 1) throw new Exception("0 length string");

        if (n > str.Length) // If number is greater than the length of the string then take MOD of the number
        {
            n = n % str.Length;
        }

        StringBuilder s1=new StringBuilder(str.Substring(n,(str.Length - n)));
        s1.Append(str.Substring(0,n));
        str=s1.ToString();


    }

///You can make a use of Skip and Take functions of the String operations

 public static void Rotate1(ref string str, int n)
    {
        if (n < 1)
            throw new Exception("Negative number for rotation"); ;
        if (str.Length < 1) throw new Exception("0 length string");

        if (n > str.Length)
        {
            n = n % str.Length;
        }

        str = String.Concat(str.Skip(n).Concat(str.Take(n)));

    }
1

you also can achieve that with a simple LINQ statement:

Note: the same can be achieved with simple for and/or while loop

string a = "ABCDEFGH";  
a = new string(Enumerable.Range(0, a.Length).Select(i => (a[(i+1)%a.Length])).ToArray());
H.G.Kh
  • 11
  • 1
1

C# 8.0

private static string ShiftString(string t, int shift)
{
    if (shift < 0)//left
    {
        shift = -shift;
        return t[shift..] + t[..shift];
    }
    else//right
    {
        return t[(t.Length - shift)..] + t[..(t.Length - shift)];
    }
}
Jay
  • 31
  • 1
  • 3