Java: 문자열에서 단어 발생 횟수 계산

개요

문자열에서 발생하는 단어 수를 계산하는 것은 상당히 쉬운 작업이지만 그렇게 하는 방법에는 여러 가지가 있습니다. 수작업을 수행하고 싶지 않을 때(예: 검색 공간이 큰 경우) 일반적으로 자동화 도구를 사용하기를 원할 것이기 때문에 방법의 효율성도 고려해야 합니다.

이 가이드에서는 Java의 문자열에서 발생하는 단어 수를 계산하는 방법을 배웁니다.

String searchText = "Your body may be chrome, but the heart never changes. It wants what it wants.";
String targetWord = "wants";

의 발생 횟수를 검색할 것입니다. targetWord사용하여, String.split(), Collections.frequency() 및 정규식.

다음을 사용하여 문자열에서 단어 발생 횟수 계산 문자열.분할()

문자열에서 대상 단어의 발생을 계산하는 가장 간단한 방법은 각 단어에서 문자열을 분할하고 배열을 반복하여 wordCount 각 경기에. 단어 주위에 다음과 같이 구두점이 있는 경우 wants. 문장의 끝에서 - 간단한 단어 수준 분할이 올바르게 처리합니다. wantswants. 별도의 단어로!

이 문제를 해결하려면 문장에서 모든 구두점을 쉽게 제거할 수 있습니다. 전에 나누기:

String[] words = searchText.replaceAll("p{Punct}", "").split(" ");

int wordCount = 0;
for (int i=0; i < words.length; i++)
    if (words[i].equals(targetWord))
        wordCount++;
System.out.println(wordCount);

. for 루프에서 배열을 반복하면서 각 인덱스의 요소가 다음과 같은지 확인합니다. targetWord. 그렇다면 우리는 wordCount, 실행이 끝나면 다음을 인쇄합니다.

2

다음을 사용하여 문자열에서 단어 발생 횟수 계산 컬렉션.빈도()

XNUMXD덴탈의 Collections.frequency() 메소드는 단순한 것을 추상화하는 훨씬 더 깨끗하고 높은 수준의 구현을 제공합니다. for 루프 및 두 ID(객체가 is 다른 대상) 및 평등(대상의 질적 특징에 따라 대상이 다른 대상과 동일한지 여부).

XNUMXD덴탈의 frequency() 이 메서드는 검색할 목록과 대상 개체를 허용하고 다른 모든 개체에서도 작동합니다. 여기서 동작은 개체 자체가 구현하는 방식에 따라 다릅니다. equals(). 스트링의 경우, equals() 에 대한 확인 문자열의 내용:


searchText = searchText.replaceAll("p{Punct}", "");

int wordCount = Collections.frequency(Arrays.asList(searchText.split(" ")), targetWord);
System.out.println(wordCount);

여기에서 얻은 배열을 변환했습니다. split() 자바로 ArrayList, 도우미 사용 asList() 방법 Arrays 수업. 감소 작업 frequency() 빈도를 나타내는 정수를 반환합니다. targetWord 목록에 있고 결과는 다음과 같습니다.

2

문자열에서 단어 발생 Matcher(정규 표현식 – RegEx)

마지막으로 정규식을 사용하여 패턴을 검색하고 일치하는 패턴의 수를 계산할 수 있습니다. 정규식은 이를 위해 만들어졌기 때문에 작업에 매우 자연스럽게 적합합니다. 자바에서는 Pattern 클래스는 정규 표현식을 표현하고 컴파일하는 데 사용되며, Matcher 클래스는 패턴을 찾고 일치시키는 데 사용됩니다.

RegEx를 사용하여 구두점 불변성을 식 자체로 코딩할 수 있으므로 문자열을 외부적으로 형식화하거나 구두점을 제거할 필요가 없습니다. 메모리에 다른 변경된 버전을 저장하는 데 비용이 많이 들 수 있는 큰 텍스트에 선호됩니다.

Pattern pattern = Pattern.compile("b%s(?!w)".format(targetWord));

Pattern pattern = Pattern.compile("bwants(?!w)");
Matcher matcher = pattern.matcher(searchText);

int wordCount = 0;
while (matcher.find())
    wordCount++;

System.out.println(wordCount);

또한 다음과 같은 결과가 발생합니다.

2

효율성 벤치마크

그렇다면 어떤 것이 가장 효율적일까요? 작은 벤치마크를 실행해 보겠습니다.

int runs = 100000;

long start1 = System.currentTimeMillis();
for (int i = 0; i < runs; i++) {
    int result = countOccurencesWithSplit(searchText, targetWord);
}

long end1 = System.currentTimeMillis();
System.out.println(String.format("Array split approach took: %s miliseconds", end1-start1));

long start2 = System.currentTimeMillis();
  for (int i = 0; i < runs; i++) {
    int result = countOccurencesWithCollections(searchText, targetWord);
}

long end2 = System.currentTimeMillis();
System.out.println(String.format("Collections.frequency() approach took: %s miliseconds", end2-start2));

long start3 = System.currentTimeMillis();
for (int i = 0; i < runs; i++) {
    int result = countOccurencesWithRegex(searchText, targetWord);
}

long end3 = System.currentTimeMillis();
System.out.println(String.format("Regex approach took: %s miliseconds", end3-start3));

각 방법은 100000번 실행됩니다(숫자가 높을수록 큰 수의 법칙으로 인해 우연으로 인한 분산 및 결과가 낮아짐). 이 코드를 실행하면 다음과 같은 결과가 나타납니다.

Array split approach took: 152 miliseconds
Collections.frequency() approach took: 140 miliseconds
Regex approach took: 92 miliseconds

그러나 – 검색을 더 크게 만들어 계산 비용이 더 많이 든다면 어떻게 될까요? 합성 문장을 생성해 보겠습니다.

List possibleWords = Arrays.asList("hello", "world ");
StringBuffer searchTextBuffer = new StringBuffer();

for (int i = 0; i < 100; i++) {
    searchTextBuffer.append(String.join(" ", possibleWords));
}
System.out.println(searchTextBuffer);

이렇게 하면 내용이 포함된 문자열이 생성됩니다.

hello world hello world hello world hello ...

모범 사례, 업계에서 인정하는 표준 및 포함된 치트 시트가 포함된 Git 학습에 대한 실습 가이드를 확인하십시오. 인터넷 검색 Git 명령을 중지하고 실제로 배움 이것!

이제 "hello" 또는 "world"를 검색하면 이전의 두 개보다 더 많은 일치 항목이 있을 것입니다. 벤치마크에서 현재 우리의 방법은 어떻게 작동합니까?

Array split approach took: 606 miliseconds
Collections.frequency() approach took: 899 miliseconds
Regex approach took: 801 miliseconds

이제 배열 분할이 가장 빨리 나옵니다! 일반적으로 벤치마크는 검색 공간, 대상 단어 등과 같은 다양한 요소에 따라 달라지며 개인 사용 사례는 벤치마크와 다를 수 있습니다.

조언: 자신의 텍스트에 방법을 시도하고 시간을 기록하고 가장 효율적이고 우아한 것을 선택하십시오.

결론

이 짧은 가이드에서는 Java의 문자열에서 대상 단어에 대한 단어 발생 수를 계산하는 방법을 살펴보았습니다. 우리는 문자열을 분할하고 간단한 카운터를 사용하여 시작한 다음 Collections 도우미 클래스, 마지막으로 정규식 사용.

결국, 우리는 방법을 벤치마킹했으며 성능이 선형이 아니며 검색 공간에 따라 다르다는 점에 주목했습니다. 일치 항목이 많은 더 긴 입력 텍스트의 경우 배열 분할이 가장 성능이 좋은 것 같습니다. 세 가지 방법을 모두 직접 시도하고 가장 성능이 좋은 방법을 선택하십시오.

타임 스탬프 :

더보기 스택카부스