在C#中移动一个字符串

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;
  }

我需要将字符串s向左移动一个空格,以便得到字符串:"BCDEFGHA"。因此,我考虑将字符串更改为字符数组,并从那里进行操作,但我不确定如何成功实现这一点。我很确定我需要一个for循环,但我需要一些帮助来将char序列向左移动一个空格。

结果看起来像什么? - spajce
你说你最终得到了“BCDEFGHA”。这不是你期望的结果吗?当输入“ABCDEFGH”时,你期望什么结果? - zs2020
抱歉,我可能表达不正确。我期望的结果是“BCDEFGHA”,但它并不是我当前的输出结果。 - user2104751
11个回答

16

这个怎么样?

public static string ShiftString(string t)
{
    return t.Substring(1, t.Length - 1) + t.Substring(0, 1); 
} 

谢谢,这似乎起作用了,但我不确定它是如何工作的。能否请您解释一下为什么会这样? - user2104751
假设你有一个字符串 ABC。这部分代码 t.Substring(1, t.Length - 1) 将返回 BC,而这个代码 t.Substring(0, 1) 将返回 A - John Woo
2
哦,等等,我可能知道了。t.Substring(1, t.Length - 1) 翻译成 "BCDEFGH",而 t.Substring(0, 1) 翻译成 "A",通过将它们连接起来,我们得到 "BCDEFGHA"? - user2104751

12
你可以尝试这个:
s = s.Remove(0, 1) + s.Substring(0, 1);

作为扩展方法:
public static class MyExtensions
{
    public static string Shift(this string s, int count)
    {
        return s.Remove(0, count) + s.Substring(0, count);
    }
}

然后您可以使用:

s = s.Shift(1);

9

解决这种关于移位 n 个位置的问题的算法是,复制字符串,连接起来并获取子字符串。 (n < 字符串长度)

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

如果您想将位置移动n个位置,您可以这样做:

var result = ss.Substring(n, s.length);

5

在C# 8及以上版本中...

将数组向右循环移动一个位置...

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

或者,向左旋转一个单位...
t = myString[1..] + myString[0];

或者,向右旋转一定的角度...
t = myString[^amount..] + myString[..^amount];

或者,向左旋转 一定量的 ...
t = myString[amount..] + myString[..amount];

3

个人而言,我会这样做:

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

    return t.Substring(1) + firstLetter;
}

抱歉,我不能为此点赞,因为该答案已被使用过了。 - Samuel Allan

2

您可以利用 stringIEnumerable<char> 的特性:

public static string ShiftString(string t){
    return new String(t.Skip(1).Concat(t).Take(t.Length).ToArray());
}

2

使用 Span<T> 可以显著提高性能。例如:

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

基准测试

使用span标签,字符串的移动既更快速,也会产生较少的垃圾。同时保留html标签。

|  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 |

完整的测试代码

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);
    }
}

1
以下方法接受数字n作为参数,用于指定字符串的移位/旋转次数。如果数字大于字符串长度,我已经对其进行了模运算。
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();


    }

您可以使用字符串操作的Skip和Take函数。

 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
StringBuilder类能够提供更好的性能。
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();
}

1
您也可以通过简单的LINQ语句实现这一点:
注意:也可以用简单的for和/或while循环实现相同的效果。
string a = "ABCDEFGH";  
a = new string(Enumerable.Range(0, a.Length).Select(i => (a[(i+1)%a.Length])).ToArray());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接