用不在括号内的逗号分隔,跳过括号内的任何内容
Split by a comma that is not inside parentheses, skipping anything inside them
我知道这可能是关于正则表达式的另一个话题,但尽管我搜索了它,但我无法得到明确的答案。所以这是我的问题-我有一个这样的字符串:
{1,2,{3,{4},5},{5,6}}
我正在删除最外面的括号(它们来自输入,我不需要它们),所以现在我有这个:
1,2,{3,{4},5},{5,6}
现在,我需要将这个字符串拆分为一个元素数组,将括号内的所有内容视为一个元素,"seamless" 元素:
Arr[0] 1
Arr[1] 2
Arr[2] {3,{4},5}
Arr[3] {5,6}
我已经尝试使用前瞻来做到这一点,但到目前为止,我失败了(悲惨地)。就正则表达式而言,处理这些事情的最巧妙方法是什么?
如果像这样的元素应该放在一起,则不能这样做:{{1},{2}}
。原因是这里的一个regex相当于解析平衡括号语言。这种语言是上下文无关的,不能使用正则表达式进行解析。处理此问题的最佳方法不是使用正则表达式,而是使用带有堆栈的 for 循环(堆栈提供解析上下文无关语言的能力)。在伪代码中我们可以这样做:
for char in input
if stack is empty and char is ','
add substring(last, current position) to output array
last = current index
if char is '{'
push '{' on stack
if char is '}'
pop from stack
此伪代码将根据需要构造数组,请注意最好遍历给定字符串中字符的索引,因为您需要这些来确定要添加到数组的子字符串的边界。
无法找出 regex
解决方案,但这里有一个非 regex
解决方案。它涉及在每个逗号(除非它是字符串中的最后一个数字)之前解析数字(不在花括号中)和解析字符串(在花括号中)直到找到组的右花括号。
如果找到正则表达式解决方案,我很乐意看到它。
public static void main(String[] args) throws Exception {
String data = "1,2,{3,{4},5},{5,6},-7,{7,8},{8,{9},10},11";
List<String> list = new ArrayList();
for (int i = 0; i < data.length(); i++) {
if ((Character.isDigit(data.charAt(i))) ||
// Include negative numbers
(data.charAt(i) == '-') && (i + 1 < data.length() && Character.isDigit(data.charAt(i + 1)))) {
// Get the number before the comma, unless it's the last number
int commaIndex = data.indexOf(",", i);
String number = commaIndex > -1
? data.substring(i, commaIndex)
: data.substring(i);
list.add(number);
i += number.length();
} else if (data.charAt(i) == '{') {
// Get the group of numbers until you reach the final
// closing curly brace
StringBuilder sb = new StringBuilder();
int openCount = 0;
int closeCount = 0;
do {
if (data.charAt(i) == '{') {
openCount++;
} else if (data.charAt(i) == '}') {
closeCount++;
}
sb.append(data.charAt(i));
i++;
} while (closeCount < openCount);
list.add(sb.toString());
}
}
for (int i = 0; i < list.size(); i++) {
System.out.printf("Arr[%d]: %s\r\n", i, list.get(i));
}
}
结果:
Arr[0]: 1
Arr[1]: 2
Arr[2]: {3,{4},5}
Arr[3]: {5,6}
Arr[4]: -7
Arr[5]: {7,8}
Arr[6]: {8,{9},10}
Arr[7]: 11
快接近要求了。 运行没时间了。稍后将完成休息(单个逗号不正确)。
正则表达式:,(?=[^}]*(?:{|$))
要检查正则表达式的有效性:转到 http://regexr.com/
要在 Java 中实现此模式,存在细微差别。 \ 需要在 { 和 } 之前添加。
因此,Java 输入的正则表达式:,(?=[^\}]*(?:\{|$))
String numbers = {1,2,{3,{4},5},{5,6}};
numbers = numbers.substring(1, numbers.length()-1);
String[] separatedValues = numbers.split(",(?=[^\}]*(?:\{|$))");
System.out.println(separatedValues[0]);
我知道这可能是关于正则表达式的另一个话题,但尽管我搜索了它,但我无法得到明确的答案。所以这是我的问题-我有一个这样的字符串:
{1,2,{3,{4},5},{5,6}}
我正在删除最外面的括号(它们来自输入,我不需要它们),所以现在我有这个:
1,2,{3,{4},5},{5,6}
现在,我需要将这个字符串拆分为一个元素数组,将括号内的所有内容视为一个元素,"seamless" 元素:
Arr[0] 1
Arr[1] 2
Arr[2] {3,{4},5}
Arr[3] {5,6}
我已经尝试使用前瞻来做到这一点,但到目前为止,我失败了(悲惨地)。就正则表达式而言,处理这些事情的最巧妙方法是什么?
如果像这样的元素应该放在一起,则不能这样做:{{1},{2}}
。原因是这里的一个regex相当于解析平衡括号语言。这种语言是上下文无关的,不能使用正则表达式进行解析。处理此问题的最佳方法不是使用正则表达式,而是使用带有堆栈的 for 循环(堆栈提供解析上下文无关语言的能力)。在伪代码中我们可以这样做:
for char in input
if stack is empty and char is ','
add substring(last, current position) to output array
last = current index
if char is '{'
push '{' on stack
if char is '}'
pop from stack
此伪代码将根据需要构造数组,请注意最好遍历给定字符串中字符的索引,因为您需要这些来确定要添加到数组的子字符串的边界。
无法找出 regex
解决方案,但这里有一个非 regex
解决方案。它涉及在每个逗号(除非它是字符串中的最后一个数字)之前解析数字(不在花括号中)和解析字符串(在花括号中)直到找到组的右花括号。
如果找到正则表达式解决方案,我很乐意看到它。
public static void main(String[] args) throws Exception {
String data = "1,2,{3,{4},5},{5,6},-7,{7,8},{8,{9},10},11";
List<String> list = new ArrayList();
for (int i = 0; i < data.length(); i++) {
if ((Character.isDigit(data.charAt(i))) ||
// Include negative numbers
(data.charAt(i) == '-') && (i + 1 < data.length() && Character.isDigit(data.charAt(i + 1)))) {
// Get the number before the comma, unless it's the last number
int commaIndex = data.indexOf(",", i);
String number = commaIndex > -1
? data.substring(i, commaIndex)
: data.substring(i);
list.add(number);
i += number.length();
} else if (data.charAt(i) == '{') {
// Get the group of numbers until you reach the final
// closing curly brace
StringBuilder sb = new StringBuilder();
int openCount = 0;
int closeCount = 0;
do {
if (data.charAt(i) == '{') {
openCount++;
} else if (data.charAt(i) == '}') {
closeCount++;
}
sb.append(data.charAt(i));
i++;
} while (closeCount < openCount);
list.add(sb.toString());
}
}
for (int i = 0; i < list.size(); i++) {
System.out.printf("Arr[%d]: %s\r\n", i, list.get(i));
}
}
结果:
Arr[0]: 1
Arr[1]: 2
Arr[2]: {3,{4},5}
Arr[3]: {5,6}
Arr[4]: -7
Arr[5]: {7,8}
Arr[6]: {8,{9},10}
Arr[7]: 11
快接近要求了。 运行没时间了。稍后将完成休息(单个逗号不正确)。
正则表达式:,(?=[^}]*(?:{|$))
要检查正则表达式的有效性:转到 http://regexr.com/
要在 Java 中实现此模式,存在细微差别。 \ 需要在 { 和 } 之前添加。
因此,Java 输入的正则表达式:,(?=[^\}]*(?:\{|$))
String numbers = {1,2,{3,{4},5},{5,6}};
numbers = numbers.substring(1, numbers.length()-1);
String[] separatedValues = numbers.split(",(?=[^\}]*(?:\{|$))");
System.out.println(separatedValues[0]);