Как я могу обнаружить и разделить слова типа «Apple 1 & 2» на «Apple 1» и «Apple 2» из списка? - PullRequest
0 голосов
/ 25 мая 2010

Входы

Papaya 2
Apple 1 & 2
Orange 1, 2 & 3
Kiwi 1 - 4
Banana1-4
Breadfruit

Желаемые выходы

Papaya 2
Apple 1
Apple 2
Orange 1
Orange 2
Orange 3
Kiwi 1
Kiwi 2
Kiwi 3
Kiwi 4
Banana 1
Banana 2
Banana 3
Banana 4
Breadfruit

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

Речь идет о CTL от CloverETL. Использование их компонента нормализатора для выполнения некоторой очистки данных. Тем не менее, я возьму любой язык ... перевод легко.

Ответы [ 4 ]

1 голос
/ 25 мая 2010

Примечание : этот ответ основан на более ранней редакции вопроса

В Java, я думаю, что-то вроде этого - то, что вы хотите:

    String[] tests = {
        "One Two 1 & 2",
        "Boeing 737 2, 4 & 6",
        "Lucky 7",
        "MI6 agent 007, 006",
        "2010-05 26, 27 & 28"
    };
    for (String test : tests) {
        String[] parts = test.split("(?=\\d+(, \\d+)*( & \\d+)?$)", 2);
        for (String number : parts[1].split("\\D+")) {
            System.out.println(parts[0] + number);
        }
    }

Это печатает: ( как видно на ideone.com )

One Two 1
One Two 2
Boeing 737 2
Boeing 737 4
Boeing 737 6
Lucky 7
MI6 agent 007
MI6 agent 006
2010-05 26
2010-05 27
2010-05 28

По сути, мы используем lookahead, чтобы разделить, где начинается специальная числовая последовательность, ограничивая разделение на 2 части. Затем последовательность специальных номеров разбивается на любую последовательность, не состоящую из цифр \D+.

Шаблон для последовательности специальных номеров, как показано на рисунке ниже:

\d+(, \d+)*( & \d+)?$

API ссылки

  • String[] split(String regex, int limit)
    • Параметр limit определяет количество применений шаблона и, следовательно, влияет на длину результирующего массива. Если предел n больше нуля, то шаблон будет применен не более n - 1 раз, длина массива не будет превышать n, а последняя запись массива будет содержать все входные данные за пределами последнего сопоставленного разделителя.

Смотри также


Одно replaceAll решение

Если по какой-либо причине вы настаиваете сделать это одним махом replaceAll, вы можете написать что-то вроде этого:

String[] tests = {
    "One Two 1 & 2",
    "Boeing 737 2, 4 & 6",
    "Lucky 7",
    "MI6 agent 007, 006",
    "2010-05 26, 27 & 28",
};
String sequence = "\\d+(?:, \\d+)*(?: & \\d+)?$";
for (String test : tests) {         
    System.out.println(
        test.replaceAll(
            "^.*?(?=sequence)|(?<=(?=(.*?)(?=sequence))^.*)(\\d+)(\\D+)?"
                .replace("sequence", sequence),
            "$1$2$3"
        )
    );
}

Вывод ( как видно на ideone.com ):

One Two 1 & One Two 2
Boeing 737 2, Boeing 737 4 & Boeing 737 6
Lucky 7
MI6 agent 007, MI6 agent 006
2010-05 26, 2010-05 27 & 2010-05 28

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

0 голосов
/ 25 мая 2010

Посмотрите на дизайн Parse::Range на CPAN:

http://cpansearch.perl.org/src/PERLER/Parse-Range-0.96/lib/Parse/Range.pm

Возможно, вам потребуется немного изменить логику для поддержки амперсандов.

0 голосов
/ 25 мая 2010

Я напишу на Perl, так как вы не указали, какой тип RegEx

Звучит так, как вы хотите (при условии отсутствия чисел в Foo Bar):

/(\D+)(\d+)(, \d+)*( & \d+)/;

Тогда $ 1 будет "Foo Bar" $ 2, $ 3 ... будут индивидуальные # с добавлением "," или "&", поэтому вам нужно будет убрать их из каждого #.

0 голосов
/ 25 мая 2010

Последняя часть может соответствовать (?:\d+, )*\d+ & \d+$. Хотя вы можете заменить пробелы на \s+. Если у вас есть подходящая строка, разделив ее на [,&\s]+, вы получите каждое число.

На самом деле, если вы используете ^(\D+) ((?:\d+, )*\d+ & \d+)$, сопоставление должно возвращать список вроде ["первая часть", "цифры"]. Таким образом, вы получите все. Разбейте вторую строку, и вы идете.

...