나는 사과, 오렌지, 배, 바나나, 키위를 말하고있다.Java Regex를 사용하여 문자열에 세트의 단어가 포함되어 있는지 확인하는 방법은 무엇입니까?
위의 단어 중 하나라도 문장에 포함되어 있는지 확인하고 싶으면 어떤 단어를 찾고 싶다. 일치. Regex에서 이것을 어떻게 수행 할 수 있습니까?
현재 각 단어 집합에 대해 String.indexOf()를 호출하고 있습니다. 나는 이것이 정규 표현식만큼 효율적이지 않다고 가정하고 있는가?
나는 사과, 오렌지, 배, 바나나, 키위를 말하고있다.Java Regex를 사용하여 문자열에 세트의 단어가 포함되어 있는지 확인하는 방법은 무엇입니까?
위의 단어 중 하나라도 문장에 포함되어 있는지 확인하고 싶으면 어떤 단어를 찾고 싶다. 일치. Regex에서 이것을 어떻게 수행 할 수 있습니까?
현재 각 단어 집합에 대해 String.indexOf()를 호출하고 있습니다. 나는 이것이 정규 표현식만큼 효율적이지 않다고 가정하고 있는가?
TL; DR을 단순 문자열
contains()
하시는 것이 좋습니다하지만입니다 정규 표현식 만 일치하면됩니다.
어떤 방법이 더 효율적인 지 확인하는 가장 좋은 방법은 테스트하는 것입니다.
String.indexOf()
대신 String.contains()
을 사용하면 정규식이 아닌 코드를 단순화 할 수 있습니다.
OR
로
apple|orange|pear|banana|kiwi
|
작동합니다.
내 아주 간단한 테스트 코드는 다음과 같습니다 : 단어의 수에 따라 달라집니다
분명히Contains took 5962ms
Regular Expression took 63475ms
타이밍은 검색과하고 다음과 같이 내가 가진
public class TestContains {
private static String containsWord(Set<String> words,String sentence) {
for (String word : words) {
if (sentence.contains(word)) {
return word;
}
}
return null;
}
private static String matchesPattern(Pattern p,String sentence) {
Matcher m = p.matcher(sentence);
if (m.find()) {
return m.group();
}
return null;
}
public static void main(String[] args) {
Set<String> words = new HashSet<String>();
words.add("apple");
words.add("orange");
words.add("pear");
words.add("banana");
words.add("kiwi");
Pattern p = Pattern.compile("apple|orange|pear|banana|kiwi");
String noMatch = "The quick brown fox jumps over the lazy dog.";
String startMatch = "An apple is nice";
String endMatch = "This is a longer sentence with the match for our fruit at the end: kiwi";
long start = System.currentTimeMillis();
int iterations = 10000000;
for (int i = 0; i < iterations; i++) {
containsWord(words, noMatch);
containsWord(words, startMatch);
containsWord(words, endMatch);
}
System.out.println("Contains took " + (System.currentTimeMillis() - start) + "ms");
start = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
matchesPattern(p,noMatch);
matchesPattern(p,startMatch);
matchesPattern(p,endMatch);
}
System.out.println("Regular Expression took " + (System.currentTimeMillis() - start) + "ms");
}
}
결과가 있었다 검색되는 문자열이지만 은 이와 같은 간단한 검색에서 정규 표현식보다 10 배 빠릅니다.
정규 표현식을 사용하여 다른 문자열 안에있는 문자열을 검색하면 너트를 깨는 데 쓰레기를 사용하고 있으므로 우리는 더 느리다는 사실에 놀라지 말아야합니다. 찾을 패턴이 더 복잡한 경우 정규 표현식을 저장하십시오. 당신은 예를 들어, 전체 단어뿐 아니라 문자열을 일치시킬 때문에 indexOf()
및 contains()
일을하지 않을 경우 정규 표현식을 사용할 수 있습니다
한 경우입니다 pear
과 일치하고 싶지 만 spears
이 아닙니다. 정규식은 word boundaries이라는 개념을 가지고 있으므로이 사례를 잘 처리합니다.
\b(apple|orange|pear|banana|kiwi)\b
\b
만 또는 식을 함께 시작 또는 단어의 끝과 괄호 그룹 일치에 말한다 :
주, 당신은 다른 백 슬래시 백 슬래시를 이스케이프해야합니다 여기
Pattern p = Pattern.compile("\\b(apple|orange|pear|banana|kiwi)\\b");
나는 정규 표현식은 성능면에서 더 나은 일을 할 것입니다 생각하지 않습니다하지만 당신은 다음과 같이 사용할 수 있습니다 :
Pattern p = Pattern.compile("(apple|orange|pear)");
Matcher m = p.matcher(inputString);
while (m.find()) {
String matched = m.group(1);
// Do something
}
내가 찾은 가장 간단한 솔루션 (와일드 카드와 일치)입니다 :
boolean a = str.matches(".*\\b(wordA|wordB|wordC|wordD|wordE)\\b.*");
그냥 읽을 수 없니? 나는 그것이 효율적이라고 결코 말하지 않았다. –
성능은 정규 표현식 길이에 따라 다릅니다. 1000 자 미만인 경우 계속하십시오. 길면 다른 해결책이 필요합니다. 예를 들어 텍스트를 분리하여 단어를 분리하고 사전 정의 된 해시 테이블/"알려진"단어 세트와 대조하십시오. – AlexR
@deporter 답변의 목적은 완벽하고 반짝이는 세계적인 솔루션을 제공하지 말아야하는 문제를 해결하는 방법에 대한 좋은 힌트를 제공하는 것입니다. 쉽게 향상시킬 수 있고 가독성을 위해 200 개의 문자열 (regexp를 사용하지 않는 또 다른 이유)이 있으면 for 루프를 사용하고'StringBuilder'에서 연결할 수 있습니다. 나는 나의 대답이 충분한 풍미를 제공한다고 생각한다. –