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

コメント投稿者が投稿したように、あなたはすでに変更されたキャラクターを変更しています。

あなたの与えられた例では、これはあなたのコードの流れでした:

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 に答える
3

あなたが抱えている問題は、すでに置き換えられているキャラクターの置き換えを行っていることです。に置き換えazから、後でに置き換えzますa

辞書を使用して値を検索し、文字をループして、新しい文字列を作成します。

    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 に答える
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

これは、キャラクターがすべて期待される範囲内にあることを前提としていますが、次のことができます。

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 に答える
1

問題は、同じ文字を 2 回置き換えていることです。文字列全体で繰り返し置換を実行するのではなく、文字列を一度に 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 に答える
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) の 2 つの範囲があり、各範囲内の文字を反転させたいとします。

したがって、単一の文字について、それが各範囲内にあるかどうかをテストし、範囲内にある場合は逆にします。

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 に答える