2015-11-05 1 views
5

Сплит без ограничений разделяет всю строку, но если вы устанавливаете предел, он разделяется до этого предела слева. Как я могу сделать то же самое по праву?Как разбить строку с лимитом, начинающимся справа в java?

"a.b.c".split("[.]", 2); // returns ["a", "b.c"] 

Я хотел бы

"a.b.c".splitRight("[.]", 2); // to return ["a.b", "c"] 

EDIT: Я хочу, чтобы общее решение, которое работает так же, как расщепляется, но обратное, так что я добавить более сложный пример

Я хотел бы

"a(->)b(->)c(->)d".splitRight("\\(->\\)", 3); // to return ["a(->)b", "c", "d"] 
+2

обратный это первый :) – blank

+0

@blank: D Смешное решение, но там слишком много вычислений, и если разделитель не является одним символом, мне тоже пришлось бы его перевернуть ... – aalku

+0

слишком много вычислений? у нас есть компьютеры для такого рода вещей! но да, это становится более сложным – blank

ответ

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 + ".*$)"; 
} 

Регулярное выражение для раскола обернут другой, поэтому для \\., вы получите: \\.(?!.*\\..*$), чтобы соответствовать и разделить на последнем вхождение в разделитель. Строка разделяется на несколько раз с помощью этого регулярного выражения, второй элемент массива результатов добавляется в список, следующий раздвоение выполняется по первому элементу массива результатов.

Эффект вышеуказанного метода для вашего примера строки как и ожидалось.

5

Вы можете использовать опережающее сравнение:

"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)}; 
} 
+0

Хорошее решение, если предел равен 2. Любой вариант, позволяющий ему быть параметром? Я не возражаю, включая somethink like '{2}' в строке регулярного выражения. И регулярное выражение специфично для этого разделителя. Нелегко адаптировать его к любому разделителю. Спасибо – aalku

+0

Я сделал именно это 'splitAtLastDot', но я подумал, есть ли общее решение, а не только для случая с лимитом 2. – aalku

+1

Я чувствую запах рекурсии – px5x2

2

Несмотря на то что вы сказали реверсирования бы долго, here's небольшая программа, которая чтит строку и разбивает ее на пределе;

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))); 
} 
+1

Это не сработает, если регулярное выражение направлено так, как '' -> "', и вы не всегда можете перевернуть регулярное выражение. – aalku

+1

Да, это не работает над более сложным регулярным выражением, но для более простого регулярного выражения это должно работать. Чтобы заставить его работать с сложным регулярным выражением, вам также придется перевернуть регулярное выражение. – SomeJavaGuy

Смежные вопросы