无限制拆分会拆分整个字符串,但如果设置了限制,则会向左拆分到该限制。我怎么能在右边做同样的事?
"a.b.c".split("[.]", 2); // returns ["a", "b.c"]
我想要
"a.b.c".splitRight("[.]", 2); // to return ["a.b", "c"]
编辑:我想要一个通用的解决方案,它的工作原理就像拆分但相反,所以我添加了一个更复杂的例子
我想要
"a(->)b(->)c(->)d".splitRight("\(->\)", 3); // to return ["a(->)b", "c", "d"]
您可以使用前瞻匹配:
"a.b.c".split("[.](?=[^.]*$)")
这里你说"我只想除以后面没有其他点的那个点"。
如果你想用最后N个点来划分,你可以用以下方式(甚至更丑陋的方式)推广这个解决方案:
"dfsga.sdgdsb.dsgc.dsgsdfg.dsdg.sdfg.sdf".split("[.](?=([^.]*[.]){0,3}[^.]*$)");
将3
替换为N-2
。
然而,我会写一个简短的静态方法:
public static String[] splitAtLastDot(String s) {
int pos = s.lastIndexOf('.');
if(pos == -1)
return new String[] {s};
return new String[] {s.substring(0, pos), s.substring(pos+1)};
}
我会尝试这样的东西:
public List<String> splitRight(String string, String regex, int limit) {
List<String> result = new ArrayList<String>();
String[] temp = new String[0];
for(int i = 1; i < limit; i++) {
if(string.matches(".*"+regex+".*")) {
temp = string.split(modifyRegex(regex));
result.add(temp[1]);
string = temp[0];
}
}
if(temp.length>0) {
result.add(temp[0]);
}
Collections.reverse(result);
return result;
}
public String modifyRegex(String regex){
return regex + "(?!.*" + regex + ".*$)";
}
split的正则表达式被另一个正则表达式包装,所以对于\.
,您将得到:\.(?!.*\..*$)
,以在最后一次出现分隔符时进行匹配和拆分。使用此正则表达式多次拆分字符串,将结果数组的第二个元素添加到List中,对结果数组的第一个元素进行下一次拆分。
上面的方法对您的示例字符串的效果是预期的。
尽管你说过反转需要很长时间,但这里有一个小程序可以反转字符串并将其按极限拆分;
static String[] leftSplit(String input, String regex, int limit) {
String reveresedInput = new StringBuilder(input).reverse().toString();
String[] output = reveresedInput.split(regex, limit);
String tempOutput[] = new String[output.length];
for(int i = 0;i<output.length;++i) {
tempOutput[tempOutput.length-i-1] = new StringBuilder(output[i]).reverse().toString();
}
return tempOutput;
}
public static void main(String[] args) {
System.out.println(Arrays.toString(leftSplit("a.b.c", "[.]", 2)));
System.out.println(Arrays.toString(leftSplit("I want to. Split this. by the. right side", "[.]", 2)));
}
性能不好,但可读性比上面的一些例子要好:
List l = Arrays.stream(new StringBuilder("a.b.c").reverse().toString().split("\.", 2))
.map(StringBuilder::new).map(StringBuilder::reverse).collect(toList());
Collections.reverse(l);