Как преобразовать алфавитно-цифровой номер телефона в цифры

Также необходимо отметить, то определение имен происходит перед разрешением перегрузки. Таким образом, если будет что-то с тем же именем в Вашей текущей области тогда, то это прекратит искать другие имена и попытается использовать их.

void bar() {};
class foo {
    void bar(int) {};
    void foobar() { bar(); } // won't compile needs ::bar()
    void foobar(int i) { bar(i); } // ok
}
6
задан alain.janinm 30 April 2012 в 21:03
поделиться

7 ответов

Оператор switch на самом деле не так уж плох. Ваш алгоритм линейен по отношению к длине телефонного номера. Код удобочитаем, и его довольно легко проверить путем проверки. Я бы не стал с этим связываться, кроме как добавить случай по умолчанию для обработки ошибок. (Я не программист на Java, так что простите меня, если он называется чем-то другим.)

Если у вас есть , чтобы ускорить работу, предварительно инициализированная таблица, проиндексированная по символам, позволит избежать любых сравнений, кроме базовых. проверка ошибок. Вы даже можете избежать преобразования регистра, продублировав значения в таблице ( цифра ['A'] = цифра ['a'] = «2»; ). Стоимость инициализации таблицы будет амортизироваться по общему количеству преобразований.

9
ответ дан 8 December 2019 в 03:53
поделиться

Можно сделать это с использованием Apache Commons Lang StringUtils, как показано ниже:

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

Предполагая, что скорость не является вашей главной заботой, конечно, и вам нужно компактное решение;)

6
ответ дан 8 December 2019 в 03:53
поделиться

Используйте карту , где клавиши - это буквы и цифры, а значение - это число на клавиатуре. (Таким образом, каждый номер клавиатуры будет проиндексирован тремя или четырьмя буквами и одной цифрой.)

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

Обновление: Мне было любопытно, будет ли справочная таблица с ручным кодированием работать лучше, чем переключатель с плотным набором случаи. В ходе своего случайного тестирования я обнаружил, что следующий код является самым быстрым, что я мог придумать:

  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 (который скомпилирован в tablewitch инструкция). Заметьте, это было просто для развлечения, но на моем ноутбуке, работающем в одном потоке, я мог преобразовать 10 миллионов 10-буквенных «чисел» примерно за 1,3 секунды. Я был очень удивлен, потому что, как я понимаю, tablewitch работает по существу таким же образом, но я ожидал, что он будет быстрее, так как это инструкция JVM.

Конечно, если только мне не платили только за каждый из неограниченного количества телефонных номеров Я мог конвертировать, я бы никогда не стал писать такой код. Коммутатор гораздо более читабелен, работает как есть и, вероятно, получит бесплатное повышение производительности в некоторых будущих JVM.

Несомненно, наибольшее улучшение исходного кода происходит от использования StringBuilder вместо конкатенации строк, и это никак не влияет на читаемость кода. Использование charAt вместо преобразования входных данных в char [] также делает код более простым и понятным и также повышает производительность. В заключение,

5
ответ дан 8 December 2019 в 03:53
поделиться

Как насчет простого:

   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;
   }
4
ответ дан 8 December 2019 в 03:53
поделиться

Если вам нужно решение, которое не заставляет вас перечислять все буквы, вы можете сделать что-то вроде:

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;
2
ответ дан 8 December 2019 в 03:53
поделиться

Операторы Switch компилируются в форму, аналогичную операторам if-else, (каждый оператор case по существу является if (c == '...' ) замаскированный тест), поэтому, хотя это визуально более компактно, чем каскадный if, этот тест для каждого символа, может быть или не быть никакого реального выигрыша в производительности.

Вы можете оптимизировать его, исключив некоторые сравнения. Ключ в том, что char - это целочисленный тип (поэтому вы можете включить char ), чтобы вы могли использовать числовые операторы сравнения. и 'a Предполагая, что ваша строка inLetters содержит только буквенно-цифровые символы, это должно работать ... (Все остальные символы будут проходить без изменений.)

String result = "";
for (char c : letters.toLowerCase().toCharArray()) {
    if      (c <= '9') result += c;
    else if (c <= 'c') result += "2";
    else if (c <= 'f') result += "3";
    else if (c <= 'i') result += "4";
    else if (c <= 'l') result += "5";
    else if (c <= 'o') result += "6";
    else if (c <= 's') result += "7";
    else if (c <= 'v') result += "8";
    else if (c <= 'z') result += "9";
    else               result += c;
}

Интересующие символы имеют шестнадцатеричные значения:' 0 '= 0x30 , ' 9 '= 0x39,' a '= 0x61 и' z '= 0x7a.

Изменить: Лучше использовать StringBuilder и append () в создать строку, но для небольших строк это вряд ли будет заметно быстрее. ( Закон Амдала демонстрирует, что фактическое ускорение, которое вы можете ожидать от оптимизации кода, ограничено процентом времени, фактически затраченным на этот код.) Я использовал только конкатенированные строки, чтобы сделать алгоритм понятным для OP.

0
ответ дан 8 December 2019 в 03:53
поделиться

Если вы запустите это 10 ^ 9 раз в узком цикле и несколько раз остановите его с Ctrl-break, я уверен, что почти каждый раз он будет глубоко в строковом классе, пытаясь выполнить одно из тех невинно выглядящих "+ = "операторы.

1
ответ дан 8 December 2019 в 03:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: