У меня есть Строка формата "[(1, 2), (2, 3), (3, 4)]"
, с произвольным числом элементов. Я пытаюсь разделить его на запятых, разделяющих координаты, то есть, получить (1, 2)
, (2, 3)
, и (3, 4)
.
Я могу сделать это в Java regex? Я - полный новичок, но Java надежды regex достаточно мощен для него. Если это не, Вы могли бы предложить альтернативу?
Для этого вы можете использовать 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
означает для цифры). .
после означает, что он должен исключить любые пустые совпадения после цифр. Однако я должен признать, что я не уверен, как исключить пустые совпадения перед цифрами. Я еще не обученный гуру регулярных выражений. Эй, Барт К., ты можешь сделать это лучше?
В конце концов, это ' В конечном итоге для этого лучше использовать парсер . См. Ответ Хубертса по этой теме .
Всегда будет 3 группы координат, которые необходимо проанализировать?
Вы можете попробовать:
\ [(\ (\ d, \ d \)), (\ d (\ D, \ d \)), (\ (\ d, \ d \)) \]
Если вы используете 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.
В Regexes вы можете разделить на (? <= \)),
, который использует положительный : :
string[] subs = str.replaceAll("\[","").replaceAll("\]","").split("(?<=\)),");
В строковых функциях Simpe вы можете отбросить [
[
и использование string.split ("),")
, и вернуть ))
после этого.
Из 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
.
Если вам не требуется выражение для проверки синтаксиса вокруг координат, это должно сделать:
\(\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);
}
}
}