codingBat Отдельные тысячи, использующие регулярные выражения (и инструкции по модульному тестированию) - PullRequest
0 голосов
/ 24 апреля 2010

Этот вопрос представляет собой сочетание практики регулярных выражений и практики модульного тестирования.

Regex part

Я создал эту проблему separateThousands для личной практики:

Задав число в виде строки, введите запятые для разделения тысяч. Число может содержать необязательный знак минуса и необязательную десятичную часть. Не будет лишних начальных нулей.

Вот мое решение:

String separateThousands(String s) {
  return s.replaceAll(
      String.format("(?:%s)|(?:%s)",
        "(?<=\\G\\d{3})(?=\\d)",
        "(?<=^-?\\d{1,3})(?=(?:\\d{3})+(?!\\d))"
      ),
      ","
  );
}

Способ работы состоит в том, что он классифицирует запятые двух типов: first и rest . В приведенном выше регулярном выражении подшаблон rest фактически появляется перед first . Совпадение всегда будет нулевой длины, которое будет replaceAll с ",".

rest в основном оглядывается назад, чтобы увидеть, было ли совпадение, за которым следуют 3 цифры, и смотрит вперед, чтобы увидеть, есть ли цифра. Это какой-то механизм цепной реакции, запущенный предыдущим матчем.

first , в основном, смотрит за якорем ^, за которым следует необязательный знак минуса и от 1 до 3 цифр. Остальная часть строки с этой точки должна соответствовать тройкам цифр, за которыми следует нецифровка (которая может быть $ или \.).

Мой вопрос к этой части:

  • Можно ли упростить это регулярное выражение?
  • Можно ли его оптимизировать дальше?
    • Заказ отдых до первый является преднамеренным, поскольку первый требуется только один раз
    • Нет группы захвата

Часть модульного тестирования

Как я уже говорил, я автор этой проблемы, поэтому я также отвечаю за разработку тестовых примеров для них. Вот они:

INPUT, OUTPUT
"1000", "1,000"
"-12345", "-12,345"
"-1234567890.1234567890", "-1,234,567,890.1234567890"
"123.456", "123.456"
".666666", ".666666"
"0", "0"
"123456789", "123,456,789"
"1234.5678", "1,234.5678"
"-55555.55555", "-55,555.55555"
"0.123456789", "0.123456789"
"123456.789", "123,456.789"

У меня не было большого опыта в тестировании промышленных модулей, поэтому мне интересно, могут ли другие прокомментировать, является ли это хорошим освещением, пропустил ли я что-нибудь важное и т. Д. (Я всегда могу добавить больше тестов, если есть сценарий, который я пропустил).

Ответы [ 2 ]

1 голос
/ 24 апреля 2010

Это работает для меня:

return s.replaceAll("(\\G-?\\d{1,3})(?=(?:\\d{3})++(?!\\d))", "$1,");

В первый раз \G действует так же, как и ^, и предвкушение заставляет \d{1,3} потреблять столько символов, сколько необходимо, чтобы покинуть позицию совпадения на границе с тремя цифрами. После этого \d{1,3} потребляет максимум три цифры каждый раз, а \G сохраняет его привязанным к концу предыдущего матча.

Что касается ваших модульных тестов, я бы просто пояснил в описании проблемы, что на входе всегда будет действительное число, самое большее с одной десятичной точкой.

1 голос
/ 24 апреля 2010

Когда вы заявляете о требованиях, намереваетесь ли вы обеспечить их соблюдение вашим методом?

Номер может содержать необязательный знак минус и необязательный десятичный часть. Там не будет никакого лишние ведущие нули.

Если ваше намерение состоит в том, чтобы метод определял, когда эти ограничения нарушаются, вам понадобятся дополнительные для написания дополнительных юнит-тестов, чтобы гарантировать выполнение договора.

Как насчет тестирования на 1234.5678.91011?

Ожидаете ли вы, что ваш метод вернет 1 234,5678,91011 или просто игнорирует все это? Лучше всего написать тест, чтобы проверить ваши ожидания

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...