我发现了很多类似的问题,但主要是关于正则表达式而不是我想要做的事情。
Given a string = "(content4(content3(content2(content1...))))
我想首先获得叶括号内容(content1 ...),而不是上面的某个级别(content2(content1 ...)),而不是上一级...依此类推。我有一些非常复杂的解决方案,但我想知道是否有一个更简单的方法。这似乎是最好的递归解决,但我还是找不到一个好的解决方案。 有人可能已经解决了类似问题。 你们有什么想法或建议吗?
事先得到你的帮助,我很感激附加:
字符串也可以如下所示:
string =“(content4(content3(content2(content1 ...); content5(content6 ...))))”
答案 0 :(得分:2)
使用堆栈。
将您的字符串分为3种类型的元素。
一个。左括号。
湾两个连续左括号之间的字符串,或者如果没有第二个左括号,则在左括号和右前括号之间有一个字符串。
℃。右括号
方法如下。
将左括号推到堆栈顶部。
将两个左括号之间的字符串推到堆栈顶部,因为第二个左括号确实存在然后转到第3步,否则将左右括号之间的字符串推到堆栈的顶部,转到步骤4。
将字符串后面的左括号(两个左括号之间的字符串)推到堆栈顶部。重复步骤1到3,直到遇到右括号。
一旦遇到右括号,请删除作为字符串的前两个元素(两个左括号之间的字符串)或者如果适用,删除字符串(左括号和右前括号之间的字符串)和左括号 从堆栈中调整顶部索引和字符串索引。现在你有了 内容1.
- 醇>
重复步骤4,直至获得所有内容。
答案 1 :(得分:1)
这似乎与理智的输入相得益彰。我没有用奇怪的测试。
public static void main(String args[]) {
ArrayList<String> split = split("(content4(content3(content2(content1...))))");
System.out.println("Split: " + split);
}
// Standard set of braces.
private static final String openBraces = "({[<";
// Matching close set.
private static final String closeBraces = ")}]>";
public static ArrayList<String> split(String s) {
// Default to splitting with my standard set of braces.
return split(s, openBraces, closeBraces);
}
// Holds the start of an element and which brace started it.
private static class Start {
// The brace number from the braces string in use.
final int brace;
// The position in the string it was seen.
final int pos;
// Constructor.
public Start(int brace, int pos) {
this.brace = brace;
this.pos = pos;
}
@Override
public String toString() {
return "{"+openBraces.charAt(brace)+","+pos+"}";
}
}
public static ArrayList<String> split(String s, String open, String close) {
// The splits.
ArrayList<String> split = new ArrayList<String>();
// The stack.
ArrayList<Start> stack = new ArrayList<Start>();
// Walk the string.
for (int i = 0; i < s.length(); i++) {
// Get the char there.
char ch = s.charAt(i);
// Is it an open brace?
int o = open.indexOf(ch);
// Is it a close brace?
int c = close.indexOf(ch);
if (o >= 0) {
// Its an open! Push it.
stack.add(new Start(o, i));
} else if ( c >= 0 && stack.size() > 0 ) {
// Pop (if matches).
int tosPos = stack.size() - 1;
Start tos = stack.get(tosPos);
// Does the brace match?
if ( tos.brace == c) {
// Matches!
split.add(s.substring(tos.pos, i+1));
// Done with that one.
stack.remove(tosPos);
}
}
}
return split;
}
打印:
Split: [(content1...), (content2(content1...)), (content3(content2(content1...))), (content4(content3(content2(content1...))))]
答案 2 :(得分:0)
我很久以前用HyperTalk做过,但算法框架保持不变:
1 - 每次遇到左大括号时,在括号中加1 2 - 关闭括号做相反的事情
每当您找到第一个左括号时,将其位置存储为+ 1,对于右括号,请执行相同的位置。
找到右括号后,提取子字符串并递归它。
如果你想首先获得更多嵌套的“叶子”,只需使用带括号位置的列表,然后向后读取你的列表(或使用堆栈)。
但请注意:这项技术只能为你带来第一个孩子。
答案 3 :(得分:0)
好的,这是一个很好的解决方案。
String str = "(content4(content3(content2(content1...))))";
str = str.replaceFirst("\\(", "");
String[] results = str.split("\\)")[0].split("\\(");
int l = results.length;
for (int j = 0; j < l / 2; j++) {
String temp = results[j];
results[j] = results[l - j - 1];
results[l - j - 1] = temp;
}
for (String string : results) {
System.out.println(string);
}
代码说明:
将字符串拆分为“)”,并将索引为0的字符串保存为数据:
字符串现在看起来像这样:
content4(content3(内容2(内容1 ...
答案 4 :(得分:0)
这是通过在大括号的两侧设置头尾标志来解决这个问题,但真正经典的方法是使用堆栈。
public static void main(String[] argv) {
String str = "(content4(content3(content2(content1...))))";
int head = str.lastIndexOf("(");
int tail = 0;
while (head != -1) {
// stop loop if the brace mismatch
if (str.substring(tail, str.length()).indexOf(")") == -1)
break;
tail += str.substring(tail, str.length()).indexOf(")") + 1;
String res = str.substring(head, tail);
System.out.println(res);
head = str.substring(0, head).lastIndexOf("(");
}
}