Java 寻找被纤度计包裹的绳子的一部分
假设我有一个Java 寻找被纤度计包裹的绳子的一部分,java,regex,recursion,Java,Regex,Recursion,假设我有一个字符串,如下所示: String s="social network such as '''[http://www.facebook.com Facebook]''' , "+ "'''[http://www.twitter.com Twitter]''' and '''[http://www.tumblr.com tumblr]'''"; 我只需要检索'[和]'中的字符串 示例输出: http://www.facebook.com Facebook, http://www.twi
字符串
,如下所示:
String s="social network such as '''[http://www.facebook.com Facebook]''' , "+
"'''[http://www.twitter.com Twitter]''' and '''[http://www.tumblr.com tumblr]'''";
我只需要检索'[
和]'
中的字符串
示例输出:
http://www.facebook.com Facebook, http://www.twitter.com Twitter, http://www.tumblr.com tumblr
我在使用regex
时遇到了困难,所以我使用递归来实现这个想法:
System.out.println(filter(s, "'''[", "]'''"));
....
public static String filter(String s, String open, String close){
int start = s.indexOf(open);
int end = s.indexOf(close);
filtered = filtered + s.substring(start + open.length(), end) + ", ";
s = s.substring(end + close.length(), s.length());
if(s.indexOf(open) >= 0 && s.indexOf(close) >= 0)
return filter(s, open, close);
else
return filtered.substring(0, filtered.length() - 2);
}
但在某些情况下,当我需要检索与字符串
相同模式中的单词时,例如在'
和'
中,它会说字符串索引超出范围,因为开始
和结束
将保持相同的值
我怎样才能克服这个问题?regex
是唯一的解决方案吗?regex是正确的工具。使用和
确保将打开
和关闭
的任何特殊字符视为常规字符
m.group()
返回由m.find()
匹配的最后一个字符串中的组
m.find()
查找与正则表达式匹配的所有子字符串
非正则表达式解决方案:
注意:在这两种情况下,end
都被分配s.indexOf(close,start+1)
,使用and,这样即使open
和close
值相同,也不会发生错误
递归:
public static String filter(String s, String open, String close){
int start = s.indexOf(open);
int end = s.indexOf(close, start + 1);
//I took the liberty of adding "String" and renaming your variable
String get = s.substring(start + open.length(), end);
s = s.substring(end + close.length());
if (s.indexOf(open) == -1){
return get;
}
return get + ", " + filter(s, open, close);
}
public static String filter(String str, String open, String close){
int open_length = open.length();
int close_length = close.length();
StringBuilder s = new StringBuilder(str);
StringBuilder filtered = new StringBuilder();
for (int start = s.indexOf(open), end = s.indexOf(close, start + 1); start != -1;
start = s.indexOf(open), end = s.indexOf(close, start + 1)){
filtered.append(s.substring(start + open_length, end)).append(", ");
s.delete(0, end + close_length);
}
return filtered.substring(0, filtered.length() - 2); //trailing ", "
}
与其立即添加,“
,不如稍后处理它。另外,请注意s.substring(end+close.length(),s.length())
与s.substring(end+close.length())相同
另外,我觉得看s.indexOf(…)==-1
比检查=0更整洁
真正的问题在于你对待过滤的的方式。首先,您需要将filtered
声明为typeString
。接下来,因为您正在执行递归,所以不应该连接到筛选的
。这将使我们第一次看到filtered
:stringfiltered=s.substring(start+open.length(),end)+“,”代码>。如果你修好了那条线,你的解决方案就行了
迭代的:
public static String filter(String s, String open, String close){
int start = s.indexOf(open);
int end = s.indexOf(close, start + 1);
//I took the liberty of adding "String" and renaming your variable
String get = s.substring(start + open.length(), end);
s = s.substring(end + close.length());
if (s.indexOf(open) == -1){
return get;
}
return get + ", " + filter(s, open, close);
}
public static String filter(String str, String open, String close){
int open_length = open.length();
int close_length = close.length();
StringBuilder s = new StringBuilder(str);
StringBuilder filtered = new StringBuilder();
for (int start = s.indexOf(open), end = s.indexOf(close, start + 1); start != -1;
start = s.indexOf(open), end = s.indexOf(close, start + 1)){
filtered.append(s.substring(start + open_length, end)).append(", ");
s.delete(0, end + close_length);
}
return filtered.substring(0, filtered.length() - 2); //trailing ", "
}
这种迭代方法使用了StringBuilder
,但是没有它也可以做到。它生成两个StringBuilder
s,一个为空,另一个保存原始String
的值。在for
循环中:
int start=s.indexOf(打开),end=s.indexOf(关闭)
获取索引的引用
开始!=-如果s
不包含open
start=s.indexOf(打开),end=s.indexOf(关闭)
循环每次迭代后,再次查找索引
循环的内部将正确的子字符串附加到finished
,并从另一个StringBuilder
中删除附加的部分。正则表达式是用于此操作的正确工具。使用和
确保将打开
和关闭
的任何特殊字符视为常规字符
m.group()
返回由m.find()
匹配的最后一个字符串中的组
m.find()
查找与正则表达式匹配的所有子字符串
非正则表达式解决方案:
注意:在这两种情况下,end
都被分配s.indexOf(close,start+1)
,使用and,这样即使open
和close
值相同,也不会发生错误
递归:
public static String filter(String s, String open, String close){
int start = s.indexOf(open);
int end = s.indexOf(close, start + 1);
//I took the liberty of adding "String" and renaming your variable
String get = s.substring(start + open.length(), end);
s = s.substring(end + close.length());
if (s.indexOf(open) == -1){
return get;
}
return get + ", " + filter(s, open, close);
}
public static String filter(String str, String open, String close){
int open_length = open.length();
int close_length = close.length();
StringBuilder s = new StringBuilder(str);
StringBuilder filtered = new StringBuilder();
for (int start = s.indexOf(open), end = s.indexOf(close, start + 1); start != -1;
start = s.indexOf(open), end = s.indexOf(close, start + 1)){
filtered.append(s.substring(start + open_length, end)).append(", ");
s.delete(0, end + close_length);
}
return filtered.substring(0, filtered.length() - 2); //trailing ", "
}
与其立即添加,“
,不如稍后处理它。另外,请注意s.substring(end+close.length(),s.length())
与s.substring(end+close.length())相同
另外,我觉得看s.indexOf(…)==-1
比检查=0更整洁
真正的问题在于你对待过滤的的方式。首先,您需要将filtered
声明为typeString
。接下来,因为您正在执行递归,所以不应该连接到筛选的
。这将使我们第一次看到filtered
:stringfiltered=s.substring(start+open.length(),end)+“,”代码>。如果你修好了那条线,你的解决方案就行了
迭代的:
public static String filter(String s, String open, String close){
int start = s.indexOf(open);
int end = s.indexOf(close, start + 1);
//I took the liberty of adding "String" and renaming your variable
String get = s.substring(start + open.length(), end);
s = s.substring(end + close.length());
if (s.indexOf(open) == -1){
return get;
}
return get + ", " + filter(s, open, close);
}
public static String filter(String str, String open, String close){
int open_length = open.length();
int close_length = close.length();
StringBuilder s = new StringBuilder(str);
StringBuilder filtered = new StringBuilder();
for (int start = s.indexOf(open), end = s.indexOf(close, start + 1); start != -1;
start = s.indexOf(open), end = s.indexOf(close, start + 1)){
filtered.append(s.substring(start + open_length, end)).append(", ");
s.delete(0, end + close_length);
}
return filtered.substring(0, filtered.length() - 2); //trailing ", "
}
这种迭代方法使用了StringBuilder
,但是没有它也可以做到。它生成两个StringBuilder
s,一个为空,另一个保存原始String
的值。在for
循环中:
int start=s.indexOf(打开),end=s.indexOf(关闭)
获取索引的引用
开始!=-如果s
不包含open
start=s.indexOf(打开),end=s.indexOf(关闭)
循环每次迭代后,再次查找索引
循环的内部将正确的子字符串附加到finished
,并从另一个StringBuilder
中删除附加的部分。您可以非常轻松地使用字符串标记器来完成此操作。只需将整个字符串交给标记器,然后询问每个标记并检查它是否以分隔符开头。如果有,则将内容提取到结果集合中
字符串标记器版本的升级将更少,也不会像regent解决方案那样丑陋
以下是标记器版本:
public class TokenizerTest {
@Test
public void canExtractNamesFromTokens(){
String openDelimiter = "'''[";
String closeDelimiter = "]'''";
String s="social network such as '''[http://www.facebook.com Facebook]''' , "+
"'''[http://www.twitter.com Twitter]''' and '''[http://www.tumblr.com tumblr]'''";
StringTokenizer t = new StringTokenizer(s);
while (t.hasMoreElements()){
String token = t.nextToken();
if (token.startsWith(openDelimiter)){
String url = token.substring(openDelimiter.length());
token = t.nextToken();
String siteName = token.substring(0, token.length()-closeDelimiter.length());
System.out.println(url + " " + siteName);
}
}
}
}
不知道这怎么会变得更简单或更干净。非常清楚代码在做什么。您可以非常轻松地使用字符串标记器来实现这一点。只需将整个字符串交给标记器,然后询问每个标记并检查它是否以分隔符开头。如果有,则将内容提取到结果集合中
字符串标记器版本的升级将更少,也不会像regent解决方案那样丑陋
我在这里