Хобрук: Ваш путь к мастерству в программировании

Масштабируемое регулярное выражение для английских цифр

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

// replace <TAG> with the content of the variable
ONE_DIGIT = (?:one|two|three|four|five|six|seven|eight|nine)
TEEN = (?:ten|eleven|twelve|(?:thir|for|fif|six|seven|eigh|nine)teen)
TWO_DIGITS = (?:(?:twen|thir|for|fif|six|seven|eigh|nine)ty(?:\s+<ONE_DIGIT>)?|<TEEN>)
// HUNDREDS, et cetera

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

13.08.2009

  • Вы уже пропустили тридцать в TWO_DIGITS. 13.08.2009
  • Кроме того, это сорок, а не сорок (не спрашивайте меня, почему, я чуть не провалил английский в старшей школе) 13.08.2009
  • Да, вы правы в обоих случаях, спасибо. На самом деле у меня была исправлена ​​первая ошибка в коде; в следующий раз я должен просто скопировать и вставить: P. 13.08.2009

Ответы:


1

См. Perl Lingua::EN::Words2Nums и Lingua::EN::FindNumber.

В частности, исходный код для Lingua::EN::FindNumber содержит:

# This is from Lingua::EN::Words2Nums, after being thrown through
# Regex::PreSuf
my $numbers =
    qr/((?:b(?:akers?dozen|illi(?:ard|on))|centillion|d(?:ecilli(?:ard|on)|ozen|u(?:o(?:decilli(?:ard|on)|vigintillion)|vigintillion))|e(?:ight(?:een|ieth|[yh])?|leven(?:ty(?:first|one))?|s)|f(?:i(?:ft(?:een|ieth|[yh])|rst|ve)|o(?:rt(?:ieth|y)|ur(?:t(?:ieth|[yh]))?))|g(?:oogol(?:plex)?|ross)|hundred|mi(?:l(?:ion|li(?:ard|on))|nus)|n(?:aught|egative|in(?:et(?:ieth|y)|t(?:een|[yh])|e)|o(?:nilli(?:ard|on)|ught|vem(?:dec|vigint)illion))|o(?:ct(?:illi(?:ard|on)|o(?:dec|vigint)illion)|ne)|qu(?:a(?:drilli(?:ard|on)|ttuor(?:decilli(?:ard|on)|vigintillion))|in(?:decilli(?:ard|on)|tilli(?:ard|on)|vigintillion))|s(?:core|e(?:cond|pt(?:en(?:dec|vigint)illion|illi(?:ard|on))|ven(?:t(?:ieth|y))?|x(?:decillion|tilli(?:ard|on)|vigintillion))|ix(?:t(?:ieth|y))?)|t(?:ee?n|h(?:ir(?:t(?:een|ieth|y)|d)|ousand|ree)|r(?:e(?:decilli(?:ard|on)|vigintillion)|i(?:gintillion|lli(?:ard|on)))|w(?:e(?:l(?:fth|ve)|nt(?:ieth|y))|o)|h)|un(?:decilli(?:ard|on)|vigintillion)|vigintillion|zero|s))/i;

подлежит лицензии Perl Artistic.

Вы можете использовать Regex::PreSuf для автоматического исключения общих пре- и суффиксов:

#!/usr/bin/perl

use strict;
use warnings;

use Regex::PreSuf;

my %singledigit = (
    one    => 1,
    two    => 2,
    three  => 3,
    four   => 4,
    five   => 5,
    six    => 6,
    seven  => 7,
    eight  => 8,
    nine   => 9,
);

my $singledigit = presuf(keys %singledigit);

print $singledigit, "\n";

my $text = "one two three four five six seven eight nine";

$text =~ s/($singledigit)/$singledigit{$1}/g;

print $text, "\n";

Вывод:

C:\Temp> cvb
(?:eight|f(?:ive|our)|nine|one|s(?:even|ix)|t(?:hree|wo))
1 2 3 4 5 6 7 8 9

Боюсь, дальше будет сложнее ;-)

13.08.2009
  • Нет, ровно наоборот. Регулярное выражение используется для поиска чисел на английском языке (включая такие фразы, как Fourscore и Seven, и преобразования их в числа. Регулярное выражение в Lingua::EN::FindNumber оптимизировано за счет исключения общих префиксов и суффиксов. Строки причудливые непонятные вызывают words2nums для каждую найденную числовую фразу, повторно вставляя все конечные пробелы, съеденные words2nums. 13.08.2009
  • Да, я понял это, когда писал комментарий, и объяснил это во втором предложении. Регулярное выражение в Lingua::EN::FindNumber оптимизировано за счет исключения общих префиксов и суффиксов. Большое спасибо за это объяснение; теперь это действительно имеет смысл :). Вы не знаете, было ли это создано вручную или сгенерировано автоматически? Кроме того, я не хочу преобразовывать слова в числа, просто хочу их распознавать. 13.08.2009
  • Если когда-либо регулярное выражение требовало обработки модификатором «x», то это оно. 13.08.2009

  • 2

    В Perl есть несколько модулей, которые создают оптимизированные регулярные выражения (которые в основном используют только стандартные функции, поэтому их можно использовать в Java) с использованием различных методов. Вы можете увидеть примеры вывода Regexp::Assemble, Regexp::List, Regexp::Optimizer и Regex::PreSuf в http://groups.google.com/group/perl.perl5.porters/msg/132877aee7542015. Начиная с perl 5.10, сам perl обычно оптимизирует списки | точных строк в trie.

    13.08.2009

    3

    Что вы пытаетесь сделать и какой алгоритм вы используете?

    Я не знаком с механизмом регулярных выражений Java, но другие механизмы регулярных выражений, которые я использовал (Perl, awk), позволяют вам захватывать совпадения. Например, если вы пытаетесь сопоставить:

    один миллион сто тысяч сто один

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

    Этот алгоритм по своей природе является рекурсивным, и его несложно реализовать. Не зная специфики того, что вы пытаетесь выполнить, или деталей механизма регулярных выражений Java, я не могу предложить больше.

    13.08.2009
  • Я просто пытаюсь распознать английские цифры в тексте. Например, в предложении В мире шесть миллиардов человек плюс около семисот семидесяти семи миллионов. Я хотел бы признать шесть миллиардов семьсот семьдесят семь миллионов. 13.08.2009

  • 4

    Regex действительно плохой способ сделать это. Лично я бы просто создал небольшую карту всех известных слов и искал таким образом. (Поищите каждое слово, когда найдете совпадение, определите, совпадают ли слова рядом с ним, и продолжайте таким образом, пока не получите число).

    13.08.2009
  • В конечном итоге вы будете делать почти то же самое, что и механизм регулярных выражений, за исключением того, что вы используете что-то вроде алгоритма Ахо-Корасика. 13.08.2009
  • Новые материалы

    Как я могу подписаться на тему изображений в ROS Matlab и получить изображение RGB?
    Привет, Пожалуйста, как я могу извлечь изображение из сообщения ROS Image, за которым следует imshow? Я уже подписался на правильную тему, но message.getData() дает мне объект..

    Понимание СТРУКТУРЫ ДАННЫХ И АЛГОРИТМА.
    Что такое структуры данных и алгоритмы? Термин «структура данных» используется для описания того, как данные хранятся, а алгоритм используется для описания того, как данные сжимаются. И данные, и..

    Как интегрировать модель машинного обучения на ios с помощью CoreMl
    С выпуском новых функций, таких как CoreML, которые упростили преобразование модели машинного обучения в модель coreML. Доступная модель машинного обучения, которую можно преобразовать в модель..

    Создание успешной организации по науке о данных
    "Рабочие часы" Создание успешной организации по науке о данных Как создать эффективную группу по анализу данных! Введение Это обзорная статья о том, как создать эффективную группу по..

    Технологии и проблемы будущей работы
    Изучение преимуществ и недостатков технологий в образовании В быстро меняющемся мире технологии являются решающим фактором в формировании будущего работы. Многие отрасли уже были..

    Игорь Минар из Google приедет на #ReactiveConf2017
    Мы рады сообщить еще одну замечательную новость: один из самых востребованных спикеров приезжает в Братиславу на ReactiveConf 2017 ! Возможно, нет двух других кланов разработчиков с более..

    Я собираюсь научить вас Python шаг за шагом
    Привет, уважаемый энтузиаст Python! 👋 Готовы погрузиться в мир Python? Сегодня я приготовил для вас кое-что интересное, что сделает ваше путешествие более приятным, чем шарик мороженого в..