2015-10-06 3 views
0

Я пытаюсь написать простую программу, которая принимает два пользовательских ввода: String, подлежащие разделению, и строку, которая указывает один или несколько разделителей. Программа должна печатать массив строк, состоящий из разломов подстрок и разделителей. Я должен реализовать публичный статический Струнный раскол [] (Строка с, Строка регулярных выражений)Java-массивы - split() с заданными пользователем разделителями

Если строка будет разделить это

cd#34#abef#1256 

Мой текущий код правильно выводит

[cd, 34, abef, 1256] 

Что мне нужно выводимый

[cd, #, 34, abef, #, 1256] 

А что если строка будет разделить два указанных пользователем разделители

cd?34?abef#1256 

Как я могу разделить, что так выглядит

[cd, ?, 34, ?, abef, #, 1256] 

Ни один из предыдущих вопросов, я заглянула в используемых пользователем указанных строк и разделителей.

Вот мой текущий код:

import java.util.Arrays; 
import java.util.Scanner; 

public class StringSplit 
{ 
    public static void main(String[] args) 
    { 
     Scanner scan = new Scanner(System.in); 
     System.out.print("Enter a string: "); 
     String str = scan.next(); 
     System.out.print("Specify delimiter(s): "); 
     String del = scan.next(); 
     String[] result = split(str, del); 
     System.out.print(Arrays.toString(result)); 
    } 

    public static String[] split(String s, String regex) 
    { 
     String[] myString = s.split(regex); 
     return myString; 
    } 
} 
+0

Я не думаю, что это какой-то стандартный способ libray для этого. Вы собираетесь реализовать свой собственный путь. –

+0

http://stackoverflow.com/questions/2206378/how-to-split-a-string-but-also-keep-the-delimiters – kan

+0

@kan, я рассмотрел этот вопрос, и это решение для строк и разделителей, которые не принимаются как пользовательский ввод. –

ответ

0

Вы можете использовать регулярное выражение непосредственно и петлю, как это:

List<String> parts = new ArrayList<>(); 
Pattern p = Pattern.compile("(#|\\?|[^#\\?]+)"); 
Matcher m = p.matcher(s); 
while(m.find()) { 
    parts.add(m.group(1)); 
} 

Обратите внимание, что регулярное выражение это просто строка. Если вы хотите использовать пользовательский разделитель, вы можете динамически создать шаблон.

4

Вы можете использовать этот предпросмотр и назад 'регулярное выражение, основанный на расщеплении:

(?<=#)|(?=#) 

Это означает разделение на позиции, где следующий символ является # или предыдущий символ является #

Для нескольких разделителей:

(?<=[?#])|(?=[?#]) 

RegEx Demo

Ваш метод Java может быть это:

public static String[] split(String s, String d) { 
    String del = Pattern.quote(d); 
    String[] myString = s.split("(?<=[" + del + "])|(?=[" + del + "])"); 
    return myString; 
} 

И называют его:

System.out.println(
    Arrays.toString(split("aa{bb}(cc)[dd]ee#ff...gg?hh*+ii", "#.?*+-[](){}")) 
); 

Выход:

[aa, {, bb, }, (, cc,), [, dd, ], ee, #, ff, ., ., ., gg, ?, hh, *, +, ii] 
+0

Умирает для следующего разделителя: '#. ? * + - []() {} ' – Andreas

+0

Теперь проверьте обновленный код, чтобы работать с' #.? * + - []() {} 'как разделители. – anubhava

+1

Не уверен, что вы можете 'quote()' внутри скобок '[]'. Хорошо знать. – Andreas

3

split() по определению исключает разделители, так что вы можете» t используйте его, если вы не используете группы с нулевой шириной/-behind, и даже тогда у вас могут быть проблемы со специальными символами.

Сделай сам:

public static List<String> split(String text, String delimiters) { 
    List<String> result = new ArrayList<>(); 
    int start = 0; 
    for (int i = 0; i < text.length(); i++) 
     if (delimiters.indexOf(text.charAt(i)) != -1) { 
      if (start < i) 
       result.add(text.substring(start, i)); 
      result.add(text.substring(i, i + 1)); 
      start = i + 1; 
     } 
    if (start < text.length()) 
     result.add(text.substring(start)); 
    return result; 
} 

Если вам необходимо вернуть значение, чтобы быть String[], изменить return заявление:

return result.toArray(new String[result.size()]); 

Test

System.out.println(split("cd#34#abef#1256", "#")); 
System.out.println(split("cd?34?abef#1256", "#?")); 
System.out.println(split("aa{bb}(cc)[dd]ee#ff...gg?hh*+ii", "#.?*+[](){}")); 

Выход

[cd, #, 34, #, abef, #, 1256] 
[cd, ?, 34, ?, abef, #, 1256] 
[aa, {, bb, }, (, cc,), [, dd, ], ee, #, ff, ., ., ., gg, ?, hh, *, +, ii] 

Примечание: Третий тест, скорее всего, не в состоянии в любой реализации, которая пытается использовать регулярное выражение.

-1

Это для одного разделителя, вы расширяете его второй разделители

import java.util.Arrays; 
import java.util.Scanner; 

public class StringSplit 
{ 
    public static void main(String[] args) 
    { 
     Scanner scan = new Scanner(System.in); 
     System.out.print("Enter a string: "); 
     String str = scan.next(); 
     System.out.print("Specify delimiter(s): "); 
     String del = scan.next(); 
     String[] result = split(str, del); 
     System.out.print(Arrays.toString(result)); 
    } 

    public static String[] split(String s, String regex) 
    { 
     String[] myString = s.split(regex); 
     int templength = myString.length; 
     String[] temp = new String[(2*templength)]; 
     int y=0; 
     for (int i=0;i<templength ;i++) { 

      temp[y] = myString[i]; 

      temp[++y] = regex; 
      y++; 

     } 
     String temp2[]= Arrays.copyOf(temp, temp.length-1); 
     return temp2; 
    } 
} 
+1

Умирает для следующего разделителя: '#.? * + - []() {}' – Andreas

0

Простое решение, используя символ [] и сравнивая каждый символ:

public static void main(String[] args) 
{ 
    // example string 
    String str = "vv*aabb?eegg?fff"; 
    char[] chars=str.toCharArray(); 

    // list of delimiters 
    List<Character> delimiters = new ArrayList<Character>(); 
    delimiters.add('*'); 
    delimiters.add('?'); 
    StringBuilder sb=new StringBuilder(); 

    for(int i=0 ; i<chars.length;i++){ 
     if (delimiters.contains(chars[i])){ 
      // if its a delimiter - add commas 
      sb.append(", " + chars[i] + ", "); 
     } else { 
      // if not - add the char only 
      sb.append(chars[i]); 
     } 
    } 
    System.out.println(sb.toString()); 
} 
-1

в вашем случае регулярное выражение должно быть выглядеть следующим образом [? #]

это как ваш раскол метод выглядит

public static String[] split(String s, String regex) 
    { 
     String[] myString = s.split("["+regex+"]"); 
     return myString; 
    } 
+1

Умирает для следующего разделителя: '#.? * + - []() {}' – Andreas

+0

, если вы ищете не- слова, почему бы не использовать [\\ W], это метасимволы должны быть экранированы, обратитесь к документам regexp http://docs.oracle.com/javase/tutorial/essential/regex/literals.html – JAVAC

+0

Я не ищу ни для чего, ни для OP. Вопрос касается пользователя *, который может ввести все, что он чувствует, как разделитель. Любой символ разделителя допускается, даже буквы и цифры и специальные символы, такие как '-' и'] '. Я просто указывал, что этот ответ не поддерживает это. – Andreas

0

Вы можете использовать регулярное выражение на основе разделителя и взломать appendReplacement/appendTail для захвата несогласованных символов. Вот код с пояснениями:

public class SplitWithDelimiter { 

    //Do compilation on build, make instance thread-safe ! 
    private final Pattern pattern; 
    public SplitWithDelimiter(String regex) { 
    pattern = Pattern.compile(regex); 
    } 

    public List<String> split(String string) { 
    List<String> substrings = new ArrayList<>(); // Value to return 

    Matcher m = pattern.matcher(string);   // Matcher to find delimiters 
    StringBuffer buffer = new StringBuffer(); // Buffer to reuse (see hack belows) 

    while (m.find()) {       // Find next 

     m.appendReplacement(buffer, "");   // Hack: Append non-matched characters to the empty buffer 
     substrings.add(buffer.toString());   // Adds buffer content 
     buffer.delete(0, buffer.length());   // Reset buffer (but keep allocate char array) 

     substrings.add(m.group());     // Adds matched delimiter 
    } 

    m.appendTail(buffer);      // Hack: Append left characters to the empty buffer 
    substrings.add(buffer.toString());   // Adds buffer content 

    return substrings; 
    } 

    public static void main(String[] args) { 

    String input = "?cd?34?abef#1256"; // User input 
    String chars = "#?"; 

    String regex = "[" + Pattern.quote(chars) + "]"; // Builds a regular expression from char list 
    List<String> splits = new SplitWithDelimiter(regex).split(input); // Do the split 
    System.out.println(splits); 
    } 
} 

Примечание: Я предполагаю, что последовательности символов разделителя являются независимыми. Если вы не просто адаптируете генерации бедных регулярных выражений из пользовательского ввода. Я также предполагаю, что вы хотите захватить пустые последовательности «несимметричных символов». Если не требуется, его легко фильтровать, когда buffer пуст.

+1

Умирает для следующего разделителя: '#.?* + - []() {} ' – Andreas

+0

Я не обращал внимания на генерацию регулярных выражений. Как сказано, это очень плохо. Я пропустил «\\», но он не выполняет работу, как я ожидал (не зная почему?). Поскольку он работает с использованием 'Pattern.quote', я заменяю его! Гораздо более чистый способ добиться генерации регулярных выражений. – LoganMzz

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