是否有更好的方法将数字替换为字母

时间:2019-09-13 21:03:25

标签: c#

我编写的代码可以正常工作,但是有办法使它变得更好

byte[] r = Convert.FromBase64String("XFEWtnopccImhpHTzGeoeXBg4ws=");
string c = BitConverter.ToString(r).Replace("-", string.Empty);
string h = c.Replace("A", "K").Replace("B", "L").Replace("C", "M").Replace("D", "N").Replace("E", "O")
    .Replace("F", "P").Replace("0", "A").Replace("1","B").Replace("2", "C").Replace("3", "D").Replace("4", "E")
    .Replace("5", "F").Replace("6", "G").Replace("7", "H").Replace("8", "I")
    .Replace("9", "J");
Console.WriteLine(h.ToLower());

0-9替换为A-J示例0-A | 1-B | 2-C 取代
A-FK-P示例A-K | B-L | C-M

输出必须为:
fmfbbglghkcjhbmccgigjbndmmghkihjhagaodal

注意:我只想知道这样做是否更简单。

编辑: 感谢所有我真的不知道哪个答案是最好的答案,但是我认为我标记为答案的应该是它!

6 个答案:

答案 0 :(得分:3)

您可以将所有char转换存储在字典中,然后使用简单的循环替换char。使用StringBuilder.Replace(使用char作为输入参数重载)应该更好,因为它可以避免在每个字符串上不断创建新字符串。调用replace,并且不必担心字符串大小的更改。

Dictionary<char, char> replacements = new Dictionary<char, char>
{
    {'A', 'K'}, {'B', 'L'}, {'C', 'M'}, {'D', 'N'}, {'E', 'O'}, {'F', 'P'},
    {'0', 'A'}, {'1', 'B'}, {'2', 'C'}, {'3', 'D'}, {'4', 'E'}, {'5', 'F'},
    {'6', 'G'}, {'7', 'H'}, {'8', 'I'}, {'9', 'J'}
};

void Main()
{

    byte[] r = Convert.FromBase64String("XFEWtnopccImhpHTzGeoeXBg4ws=");
    string c = BitConverter.ToString(r).Replace("-", string.Empty);

    StringBuilder sb = new StringBuilder(c);
    foreach(char x in replacements.Keys)
        sb.Replace(x, replacements[x]);
    Console.WriteLine(sb.ToString().ToLower());
 }

答案 1 :(得分:2)

BitConverter.ToString(r).Replace()这东西简直令人难以置信。

const string lookup = "abcdefghijklmnop";

byte[] r = Convert.FromBase64String("XFEWtnopccImhpHTzGeoeXBg4ws=");
string h = string.Concat(r.Select(b => "" +  lookup[b >> 4] + lookup[b & 0xf]));

System.Diagnostics.Debug.Assert(h == "fmfbbglghkcjhbmccgigjbndmmghkihjhagaodal");

优化代码:

const string lookup = "abcdefghijklmnop";
public string Decode(string input)
{
    byte[] buf = Convert.FromBase64String(input);
    var result = new StringBuilder(buf.Length*2);
    foreach (byte b in buf)
    {
        result.Append(lookup[b >> 4]).Append(lookup[b & 0xf]);
    }
    return result.ToString();
}

string h = Decode("XFEWtnopccImhpHTzGeoeXBg4ws=");
System.Diagnostics.Debug.Assert(h == "fmfbbglghkcjhbmccgigjbndmmghkihjhagaodal");

答案 2 :(得分:1)

您还可以执行以下操作:

static string DecodeWithoutLinq(string encoded)
{
    char[] s = new char[encoded.Length];

    for (int i = 0; i < encoded.Length; i++)
    {
        char currentChar = encoded[i];

        if (char.IsLetter(currentChar))
            s[i] = (char)(encoded[i] + 10);
        else if (char.IsNumber(currentChar))
            s[i] = (char)('A' + (currentChar - '0'));
    }
    return new string(s).ToLower();
}

static string DecodeWithLinq(string encoded)
{
    return string.Concat(encoded.ToCharArray()
        .Select(s => char.IsLetter(s) ? (char)(s + 10) : (char)('A' + (s - '0')))).ToLower();
}

static void Main(string[] args)
{
    byte[] r = Convert.FromBase64String("XFEWtnopccImhpHTzGeoeXBg4ws=");
    string c = BitConverter.ToString(r).Replace("-", string.Empty);

    string decodedString1 = DecodeWithoutLinq(c);
    string decodedString2 = DecodeWithLinq(c);
    Console.WriteLine(decodedString1);
    Console.WriteLine(decodedString2);

    Console.ReadKey();
}

一种不涉及字符串操作的方式。

DecodeWithLinq不会验证它是否是数字。可以根据需要轻松添加。

答案 3 :(得分:0)

这是我的解决方案,它使用了几个数组和少量的Linq。

void Main()
{
    string inputChars = "0123456789ABCDEF";
    string replacementChars = "ABCDEFGHIJKLMNOP";

    byte[] r = Convert.FromBase64String("XFEWtnopccImhpHTzGeoeXBg4ws=");
    string c = BitConverter.ToString(r);

    string result = new String(c.Where(ch => inputChars.Contains(ch))
                                .Select(ch => replacementChars[inputChars.IndexOf(ch)])
                                .ToArray());

    Console.WriteLine(result.ToLower());
}

答案 4 :(得分:0)

如果您事先知道长度(在这种情况下可以这样做),. Net Core现在比StringBuilder的{​​{3}}(至少在性能方面):

private static Dictionary<char, char> map = new Dictionary<char, char> {
    {'A', 'k'}, {'B', 'l'}, {'C', 'm'}, {'D', 'n'}, {'E', 'o'}, {'F', 'p'},
    {'0', 'a'},{'1', 'b'}, {'2', 'c'}, {'3', 'd'},{'4', 'e'}, {'5', 'f'},
    {'6', 'g'},{'7', 'h'},{'8', 'i'}, {'9', 'j'}
};

public static string GetMyString(string input)
{
    byte[] b = Convert.FromBase64String(input);
    string source = BitConverter.ToString(b);

    return string.Create(2*(input.Length+1)/3 , input, (r, d) => {
        int j = 0;
        foreach(char c in d)
        {   
            if (c == '-') continue;
            r[j++] = map[c];
        }
    });
}

Console.WriteLine(GetMyString("XFEWtnopccImhpHTzGeoeXBg4ws="));

如果我要使用StringBuilder,我知道我可以轻松地删除最后一个.Replace()调用和ToLower()调用,这两个调用都会分配和复制整个新字符串:

public static string GetMyString(string input)
{
    byte[] b = Convert.FromBase64String(input);
    string source = BitConverter.ToString(b);

    var result = new StringBuilder(2*(input.Length+1)/3);
    foreach(char c in input)
    {
        if (c == '-') continue;
        result.Append(map[c]);
    }
    return result.ToString();
}

我还没有进行基准测试,但是我希望它会大大胜过其他基于Dictionary / StringBuilder的答案……但这就是我花更长的时间回答并提供两种解决方案的原因;)

even better option

答案 5 :(得分:0)

正则表达式解决方案如何?

const renderTextField = ({
  input,
  label,
  value,
  meta: { touched, error },
  ...custom
}) => (
    <TextField
      fullWidth
      multiline
      rowsMax="1"
      autoFocus
      margin="normal"
      {...input}
      {...custom}
    />
  )

run it on dotnetfiddle