Java Regex проверяет предыдущий символ перед разбиением - PullRequest
4 голосов
/ 11 января 2011

У меня есть такая строка

This: string: must ~: be: split: когда: previous: char: is: not ~: this

Мне нужно разбить строкус разделителем ":", но только если символ перед разделителем НЕ "~"

Теперь у меня есть следующее регулярное выражение:

String[] split = str.split(":(?<!~:)");

Это работает, но с тех пор как я дошел до негоЧисто методом проб и ошибок я не уверен, что это самый эффективный способ сделать это.Кроме того, эта функция будет часто вызываться для больших строк, поэтому производительность учитывается.Какой более эффективный способ сделать это?

Ответы [ 3 ]

5 голосов
/ 11 января 2011

Немного более простой подход заключается в следующем:

(?<!~):

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

2 голосов
/ 11 января 2011

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

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

public static void main(String[] args) {
    Pattern pattern = Pattern.compile(":(?<!~:)");
    for (int runs = 0; runs < 4; ++runs) {
        long start = System.currentTimeMillis();
        for (int index = 0; index < 100000; ++index) {
            "This:string:must~:be:split:when:previous:char:is:not~:this".split(":(?<!~:)");
        }
        long stop = System.currentTimeMillis();
        System.out.println("Run: " + runs + " Regex: " + (stop - start));

        start = System.currentTimeMillis();
        for (int index = 0; index < 100000; ++index) {
            pattern.split("This:string:must~:be:split:when:previous:char:is:not~:this");
        }
        stop = System.currentTimeMillis();
        System.out.println("Run: " + runs + " Compiled Regex: " + (stop - start));

        start = System.currentTimeMillis();
        for (int index = 0; index < 100000; ++index) {
            specialSplit("This:string:must~:be:split:when:previous:char:is:not~:this");
        }
        stop = System.currentTimeMillis();
        System.out.println("Run: " + runs + " Custom: " + (stop - start));
    }

    for (String s : specialSplit("This:string:must~:be:split:when:previous:char:is:not~:this")) {
        System.out.println(s);
    }
}

public static String[] specialSplit(String text) {
    List<String> stringsAfterSplit = new ArrayList<String>();

    StringBuilder splitString = new StringBuilder();
    char previousChar = 0;
    for (int index = 0; index < text.length(); ++index) {
        char charAtIndex = text.charAt(index);
        if (charAtIndex == ':' && previousChar != '~') {
             stringsAfterSplit.add(splitString.toString());
             splitString.delete(0, splitString.length());
        } else {
                splitString.append(charAtIndex);
        }
            previousChar = charAtIndex;
    }
    if (splitString.length() > 0) {
        stringsAfterSplit.add(splitString.toString());
    }
    return stringsAfterSplit.toArray(new String[stringsAfterSplit.size()]);
}

Выход

Run: 0 Regex: 468
Run: 0 Compiled Regex: 365
Run: 0 Custom: 169
Run: 1 Regex: 437
Run: 1 Compiled Regex: 363
Run: 1 Custom: 166
Run: 2 Regex: 445
Run: 2 Compiled Regex: 363
Run: 2 Custom: 167
Run: 3 Regex: 436
Run: 3 Compiled Regex: 361
Run: 3 Custom: 167
This
string
must~:be
split
when
previous
char
is
not~:this
0 голосов
/ 11 января 2011

Попробуйте это. [^~]:

Проверено в JS

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...