有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何将字母数字电话号码转换为数字

更新:

my utility的最终版本如下所示:

StringBuilder b = new StringBuilder();

for(char c : inLetters.toLowerCase().toCharArray())
{
    switch(c)
    {
    case '0':                                          b.append("0"); break;
    case '1':                                          b.append("1"); break;
    case '2': case 'a': case 'b': case 'c':            b.append("2"); break;
    case '3': case 'd': case 'e': case 'f':            b.append("3"); break;
    case '4': case 'g': case 'h': case 'i':            b.append("4"); break;
    case '5': case 'j': case 'k': case 'l':            b.append("5"); break;
    case '6': case 'm': case 'n': case 'o':            b.append("6"); break;
    case '7': case 'p': case 'q': case 'r': case 's':  b.append("7"); break;
    case '8': case 't': case 'u': case 'v':            b.append("8"); break;
    case '9': case 'w': case 'x': case 'y': case 'z':  b.append("9"); break;
    }
}

return builder.toString();

原始问题:

我正在承担将字母数字电话号码转换为一串数字的简单任务。例如,1-800-HI-HAXOR将变成1-800-44-42967。我最初的尝试是创建一个讨厌的switch语句,但我希望有一个更优雅、更高效的解决方案。以下是我得到的:

for(char c : inLetters.toLowerCase().toCharArray())
{
    switch(c)
    {
    case '0':                                         result+="0"; break;
    case '1':                                         result+="1"; break;
    case '2': case 'a': case 'b': case 'c':           result+="2"; break;
    case '3': case 'd': case 'e': case 'f':           result+="3"; break;
    case '4': case 'g': case 'h': case 'i':           result+="4"; break;
    case '5': case 'j': case 'k': case 'l':           result+="5"; break;
    case '6': case 'm': case 'n': case 'o':           result+="6"; break;
    case '7': case 'p': case 'q': case 'r': case 's': result+="7"; break;
    case '8': case 't': case 'u': case 'v':           result+="8"; break;
    case '9': case 'w': case 'x': case 'y': case 'z': result+="9"; break;
    }
}

谢谢


共 (6) 个答案

  1. # 1 楼答案

    简单地说:

       String convert(String inLetters) {
          String digits = "22233344455566677778889999";
          String alphas = "abcdefghijklmnopqrstuvwxyz";
          String result = "";
          for (char c : inLetters.toLowerCase().toCharArray()) {
              int pos = alphas.indexOf(c);
              result += (pos == -1 ? c : digits.charAt(pos));
          }
          return result;
       }
    
  2. # 2 楼答案

    如果您想要一个不会强迫您枚举所有字母的解决方案,您可以执行以下操作:

    char convertedChar = c;
    if (Character.isLetter(c)) {
        //lowercase alphabet ASCII codes: 97 (a)-122 (z)
        int charIndex = ((int)c) - 97;
        //make adjustments to account for 's' and 'z'
        if (charIndex >= 115) { //'s'
            charIndex--;
        }
        if (charIndex == 121) { //'z'-1
            charIndex--;
        }
        convertedChar = (char)(2 + (charIndex/3));
    }
    result += convertedChar;
    
  3. # 3 楼答案

    使用Map,其中键是字母和数字,值是键盘上的数字。(因此,每个键盘号码将由三个或四个字母和一个数字索引)

    Map<Character, Character> keypad = new HashMap<Character, Character>();
    ...
    StringBuilder buf = new StringBuilder(inLetters.length());
    for (int idx = 0; idx < inLetters.length(); ++idx) {
      Character ch = keypad.get(inLetters.charAt(idx));
      if (ch != null)
        buf.append(ch);
    }
    

    更新:我很好奇手工编码的查找表是否比密集集switch情况更好。在我的非正式测试中,我发现以下代码是我能想到的最快的代码:

      private static final char[] lut = 
        "0123456789:;<=>?@22233344455566677778889999[\\]^_`22233344455566677778889999".toCharArray();
    
      private static final char min = lut[0];
    
      String fastest(String letters)
      {
        int n = letters.length();
        char[] buf = new char[n];
        while (n-- > 0) {
          int ch = letters.charAt(n) - min;
          buf[n] = ((ch < 0) || (ch >= lut.length)) ? letters.charAt(n) : lut[ch];
        }
        return new String(buf);
      }
    

    令人惊讶的是,它的速度是使用switch语句(编译成tableswitch指令)的类似代码的两倍多。请注意,这只是为了好玩,但在我的笔记本电脑上,运行在一个线程中,我可以在大约1.3秒内转换1000万个10个字母的“数字”。我真的很惊讶,因为据我所知,tableswitch的运行方式基本相同,但我希望它会更快,因为它是一条JVM指令

    当然,除非我只为我可以转换的无限数量的电话号码中的每一个获得报酬,否则我永远不会写这样的代码。交换机的可读性更强,性能也更好,并且可能在未来的JVM中获得免费的性能提升

    毫无疑问,对原始代码最大的改进来自于使用StringBuilder而不是串接字符串,这不会影响代码的可读性。使用charAt而不是将输入转换为char[]也使代码更简单、更容易理解也提高了性能。最后,添加char文本而不是String文本('1'而不是"1")是一种性能改进,也有助于提高可读性

  4. # 4 楼答案

    您可以使用Apache Commons Lang StringUtils实现这一点,如下所示:

    String output = StringUtils.replaceChars(StringUtils.lowerCase(input),
                        "abcdefghijklmnopqrstuvwxyz",
                        "22233344455566677778889999");
    

    当然,假设速度不是您主要关心的问题,并且您想要一个紧凑的解决方案;)

  5. # 5 楼答案

    switch语句并没有那么糟糕。您的算法与电话号码的长度成线性关系。代码是可读的,并且很容易通过检查进行验证。我不会搞砸它,除了添加一个default案例来处理错误。(我不是Java程序员,所以如果它被称为其他东西,请原谅。)

    如果需要来加快速度,则按字符索引的预初始化表将避免基本错误检查之外的任何比较。您甚至可以通过复制表(digit['A'] = digit['a'] = "2";)中的值来避免大小写转换。初始化表的成本将在转换总数中摊销

  6. # 6 楼答案

    如果在紧循环中运行10^9次,并按ctrl键将其打断几次,我敢打赌,几乎每次它都会深入string类,试图完成一个看似无辜的“+=”运算符