2

我想知道如何反转字符串中的单个字符,而不是从字面上反转整个字符串。我使用了下面显示的代码并得到了以下结果。我还将展示结果应该是什么。

  • 输入:a29z3
  • 输出:a20a3
  • 应该是什么:z70a6

正如你所看到的,我没有得到我一开始所期望的结果。每个单独的字符都应该颠倒,但我很好奇如何做到这一点。上面的结果是我使用以下代码得到的结果:

static void Main()
    {
        string input = "a29z3";

        //Reverse Letters
        input = input.Replace("a", "z");
        input = input.Replace("b", "y");
        input = input.Replace("c", "x");
        input = input.Replace("d", "w");
        input = input.Replace("e", "v");
        input = input.Replace("f", "u");
        input = input.Replace("g", "t");
        input = input.Replace("h", "s");
        input = input.Replace("i", "r");
        input = input.Replace("j", "q");
        input = input.Replace("k", "p");
        input = input.Replace("l", "o");
        input = input.Replace("m", "n");
        input = input.Replace("n", "m");
        input = input.Replace("o", "l");
        input = input.Replace("p", "k");
        input = input.Replace("q", "j");
        input = input.Replace("r", "i");
        input = input.Replace("s", "h");
        input = input.Replace("t", "g");
        input = input.Replace("u", "f");
        input = input.Replace("v", "e");
        input = input.Replace("w", "d");
        input = input.Replace("x", "c");
        input = input.Replace("y", "b");
        input = input.Replace("z", "a");

        //Reverse numbers
        input = input.Replace("0", "9");
        input = input.Replace("1", "8");
        input = input.Replace("2", "7");
        input = input.Replace("3", "6");
        input = input.Replace("4", "5");
        input = input.Replace("5", "4");
        input = input.Replace("6", "3");
        input = input.Replace("7", "2");
        input = input.Replace("8", "1");
        input = input.Replace("9", "0");

        Console.WriteLine(input);
    }

建议和/或示例将非常受欢迎!

4

7 回答 7

3

您遇到的问题是您正在对已经被替换的字符进行替换。您替换az,然后您稍后替换za.

我会使用字典来查找值并遍历字符,构建一个新字符串:

    Dictionary<string, string> ReplaceDict = new Dictionary<string, string>();
    private void Form1_Load(object sender, EventArgs e)
    {
        //Reverse Letters
        ReplaceDict.Add("a", "z");
        ReplaceDict.Add("b", "y");
        ReplaceDict.Add("c", "x");
        ReplaceDict.Add("d", "w");
        ReplaceDict.Add("e", "v");
        ReplaceDict.Add("f", "u");
        ReplaceDict.Add("g", "t");
        ReplaceDict.Add("h", "s");
        ReplaceDict.Add("i", "r");
        ReplaceDict.Add("j", "q");
        ReplaceDict.Add("k", "p");
        ReplaceDict.Add("l", "o");
        ReplaceDict.Add("m", "n");
        ReplaceDict.Add("n", "m");
        ReplaceDict.Add("o", "l");
        ReplaceDict.Add("p", "k");
        ReplaceDict.Add("q", "j");
        ReplaceDict.Add("r", "i");
        ReplaceDict.Add("s", "h");
        ReplaceDict.Add("t", "g");
        ReplaceDict.Add("u", "f");
        ReplaceDict.Add("v", "e");
        ReplaceDict.Add("w", "d");
        ReplaceDict.Add("x", "c");
        ReplaceDict.Add("y", "b");
        ReplaceDict.Add("z", "a");

        //Reverse numbers
        ReplaceDict.Add("0", "9");
        ReplaceDict.Add("1", "8");
        ReplaceDict.Add("2", "7");
        ReplaceDict.Add("3", "6");
        ReplaceDict.Add("4", "5");
        ReplaceDict.Add("5", "4");
        ReplaceDict.Add("6", "3");
        ReplaceDict.Add("7", "2");
        ReplaceDict.Add("8", "1");
        ReplaceDict.Add("9", "0");
    }

    private void button1_Click_1(object sender, EventArgs e)
    {
        StringBuilder output = new StringBuilder();
        string input = "a29z3";

        foreach (var c in input.ToCharArray())
        {
            output.Append(ReplaceDict[c.ToString()]);
        }

        MessageBox.Show(output.ToString()); 
    }
于 2013-01-15T22:10:18.620 回答
3

正如您的评论者所发布的那样,您正在更改已经更改的字符。

在您给定的示例中,这将是您的代码的流程:

a29z3
z29z3 -> a 到 z
a29a3 -> z 到 a
a79a3 -> 2 到 7
a79a6 -> 3 到 6
a79a3 -> 6 到 3
a29a3 -> 7 到 2
a20a3 -> 9 到 0

此方法将遍历给定的字符串。

// build the map; there's most likely a better way
var alpha = "abcdefghijklmnopqrstuvwxyz";
var digits = "0123456789";

var alphaMap = alpha.Zip(alpha.Reverse(), (k, v) => new {Key = k, Value = v});
var digitMap = digits.Zip(digits.Reverse(), (k, v) => new { Key = k, Value = v });

var map = alphaMap.Concat(digitMap)
                  .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);


// execute
var given = "a29z3";
Debug.WriteLine(new string(given.Select(c => map[c]).ToArray()));
// yields:  z70a6
于 2013-01-15T22:17:20.143 回答
2

发生的事情是这样的:

  1. 让我们说input = "a"
  2. input = input.Replace("a", "z");执行,现在input = "z"
  3. 几行之后input = input.Replace("a", "z");执行,现在input = "a"

您需要做的不是替换您构建一个新字符串。因此,您遍历字符串中的字符,找到相反的内容,并将其附加到新字符串中。

于 2013-01-15T22:11:09.307 回答
1

问题是您要替换相同的字母两次。您需要一次遍历字符串一项并替换每个字符,而不是在整个字符串上重复运行替换。

例如,像这样:

    static void Main(string[] args) {

    string input = "a29z3";
    string output = string.Empty;

    foreach (char letter in input.ToCharArray()) {
        output += replacementChar(letter);
    }

    Console.WriteLine(output);

    }

    static char replacementChar(char c) {

        switch (c) {
            case 'a': return 'z'; 
            case 'b': return 'y'; 
            // and so on

            default: return c;
        }

    }

我还建议使用对 ASCII 值的计算来进行交换,而不是单独列出一长串替换。会更干净。

于 2013-01-15T22:05:16.137 回答
1

这假设您的字符都在预期范围内,但您可以这样做:

public static char Reverse(char c)
{
    if (Char.IsDigit(c))
    {
        return (char)((int)'9' - (int)c + (int)'0');
    }
    else
    {
        return (char)((int)'z' - (int)c + (int)'a');
    }
}

然后Select用来做映射:

string output = new string(input.Select(Reverse).ToArray());
于 2013-01-15T22:16:13.943 回答
0

单线(代码打高尔夫球):

input = input.Aggregate(string.Empty, (s, c) => s + ((c >= 'a') && (c <= 'z') ? (char)('z' - c + 'a') : (c >= '0') && (c <= '9') ? (char)('9' - c + '0') : c));
于 2013-01-15T22:40:52.367 回答
0

其他人已经发现了这个问题:你用另一个字符替换了一个字符,但在某些情况下又用它的原始值替换了那个字符。

为了更好地编写代码,让我们重述问题:您有两个连续字符范围(az 和 0-9),并且您希望反转每个范围内的字符。

因此,对于单个字符,我们测试它是否在每个范围内,如果是,我们将其反转:

private static readonly Tuple<char, char>[] Ranges =
    new[] { Tuple.Create('a', 'z'), Tuple.Create('0', '9') };

static char Reverse(char c)
{
    foreach (var range in Ranges)
    {
        var first = range.Item1;
        var last = range.Item2;

        if (c >= first && c <= last)
        {
            int index = c - first;
            int reverseIndex = (last - first) - index;
            return (char)(first + reverseIndex);
        }
    }
    return c;
}

这样,例如添加 AZ 范围将是一个非常简单的代码更改。

(我Tuple在这里使用,因为它很简单。如果您使用更多的字符范围,为它创建自定义类型会很有意义。)

现在,反转字符串意味着反转每个字符,这正是Select()它的用途。但是结果是IEnumerable,所以我们需要把它转回一个字符串:

static string Reverse(string s)
{
    return string.Concat(s.Select(Reverse));
}
于 2013-01-15T22:56:47.610 回答