Regex для разделения вложенных координатных строк

У меня есть Строка формата "[(1, 2), (2, 3), (3, 4)]", с произвольным числом элементов. Я пытаюсь разделить его на запятых, разделяющих координаты, то есть, получить (1, 2), (2, 3), и (3, 4).

Я могу сделать это в Java regex? Я - полный новичок, но Java надежды regex достаточно мощен для него. Если это не, Вы могли бы предложить альтернативу?

10
задан Paul Wagland 1 February 2010 в 22:26
поделиться

6 ответов

Для этого вы можете использовать String # split () .

String string = "[(1, 2), (2, 3), (3, 4)]";
string = string.substring(1, string.length() - 1); // Get rid of braces.
String[] parts = string.split("(?<=\\))(,\\s*)(?=\\()");
for (String part : parts) {
    part = part.substring(1, part.length() - 1); // Get rid of parentheses.
    String[] coords = part.split(",\\s*");
    int x = Integer.parseInt(coords[0]);
    int y = Integer.parseInt(coords[1]);
    System.out.printf("x=%d, y=%d\n", x, y);
}

(? <= \\)) положительный просмотр назад означает, что ему должен предшествовать ) . Положительный прогноз (? = \\ () ] означает, что ему должен предшествовать (. (, \\ s *) означает, что он должен быть разделен на , и любое пространство после этого. \\ здесь только для того, чтобы избежать символов, специфичных для регулярных выражений.

Тем не менее, конкретная строка распознается как результат List # toString () . Вы уверены, что делаете все правильно?;)

Обновите согласно комментариям, вы действительно можете сделать наоборот и избавьтесь от нецифровых цифр:

String string = "[(1, 2), (2, 3), (3, 4)]";
String[] parts = string.split("\\D.");
for (int i = 1; i < parts.length; i += 3) {
    int x = Integer.parseInt(parts[i]);
    int y = Integer.parseInt(parts[i + 1]);
    System.out.printf("x=%d, y=%d\n", x, y);
}

Здесь \\ D означает, что он должен быть разделен на любую не -цифру ( \\ d означает для цифры). . после означает, что он должен исключить любые пустые совпадения после цифр. Однако я должен признать, что я не уверен, как исключить пустые совпадения перед цифрами. Я еще не обученный гуру регулярных выражений. Эй, Барт К., ты можешь сделать это лучше?

В конце концов, это ' В конечном итоге для этого лучше использовать парсер . См. Ответ Хубертса по этой теме .

7
ответ дан 3 December 2019 в 18:33
поделиться

Всегда будет 3 группы координат, которые необходимо проанализировать?

Вы можете попробовать:

\ [(\ (\ d, \ d \)), (\ d (\ D, \ d \)), (\ (\ d, \ d \)) \]

1
ответ дан 3 December 2019 в 18:33
поделиться
121 --- 3470345-

Если вы используете Regex, вы собираетесь получить отчеты о паршивом ошибках, и все получится Экспоненциально сложнее, если ваши требования изменяются (например, если вы должны разбирать множества в различных квадратных скобках в разные группы).

Я рекомендую вам просто написать парсер вручную, это как 10 строк кода и не должно быть очень хрупким. Отслеживайте все, что вы делаете, Открыть Parens, Закрыть Parens, открытые брекеты и закрытые брекеты. Это как оператор коммутатора с 5 вариантами (по умолчанию), действительно не так плохо.

Для минимального подхода открываются открытые и открытые брекеты могут игнорироваться, поэтому существуют действительно только 3 случая.


Это будет минимум медведя.

// Java-like psuedocode
int valuea;
String lastValue;
tokens=new StringTokenizer(String, "[](),", true);

for(String token : tokens) {  

    // The token Before the ) is the second int of the pair, and the first should
    // already be stored
    if(token.equals(")"))
        output.addResult(valuea, lastValue.toInt());

    // The token before the comma is the first int of the pair
    else if(token.equals(",")) 
        valuea=lastValue.toInt();

    // Just store off this token and deal with it when we hit the proper delim
    else
        lastValue=token;
}

Это не лучше, чем минимальное решение на основе REGEX, за исключением того, что его будет намного проще поддерживать и улучшать. (Добавьте проверку ошибки, добавьте стек для сопоставления и проверки скобок Paren & Square и проверки неуместных запятых и других недействительных синтаксиса)

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

    // When we close the square bracket, start a new output group.
    else if(token.equals("]"))
        output.startNewGroup();

, и проверка для Parens так же просто, как создание стопки символов и нажимает каждый [или (на стек, затем, когда вы получаете] или), поп-стек и утверждать, что он соответствует. Кроме того, когда вы закончите, убедитесь, что ваш стек.size () == 0.

1
ответ дан 3 December 2019 в 18:33
поделиться

В Regexes вы можете разделить на (? <= \)), , который использует положительный : :

string[] subs = str.replaceAll("\[","").replaceAll("\]","").split("(?<=\)),");

В строковых функциях Simpe вы можете отбросить [ [ и использование string.split ("),") , и вернуть )) после этого.

0
ответ дан 3 December 2019 в 18:33
поделиться

Из Java 5

Scanner sc = new Scanner();
sc.useDelimiter("\\D+"); // skip everything that is not a digit
List<Coord> result = new ArrayList<Coord>();
while (sc.hasNextInt()) {
    result.add(new Coord(sc.nextInt(), sc.nextInt()));
}
return result;

РЕДАКТИРОВАТЬ: Мы не знаем, сколько координат передается в строке coords .

9
ответ дан 3 December 2019 в 18:33
поделиться

Если вам не требуется выражение для проверки синтаксиса вокруг координат, это должно сделать:

\(\d+,\s\d+\)

Это выражение вернет несколько совпадений (три с вводом из вашего примера).

В своем вопросе вы заявляете, что хотите «получить (1, 2) , (2, 3) и (3, 4) . В случае, если вам действительно нужна пара значений, связанных с каждой координатой, вы можете опустить круглые скобки и изменить регулярное выражение для выполнения некоторых захватов:

(\d+),\s(\d+)

Код Java будет выглядеть примерно так:

import java.util.regex.*;

public class Test {
    public static void main(String[] args) {
        Pattern pattern = Pattern.compile("(\\d+),\\s(\\d+)");
        Matcher matcher = pattern.matcher("[(1, 2), (2, 3), (3, 4)]");

        while (matcher.find()) {
            int x = Integer.parseInt(matcher.group(1));
            int y = Integer.parseInt(matcher.group(2));
            System.out.printf("x=%d, y=%d\n", x, y);
        }
    }
}
3
ответ дан 3 December 2019 в 18:33
поделиться
Другие вопросы по тегам:

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