Programing

문자열에서 문자 발생 횟수를 어떻게 계산합니까?

lottogame 2020. 2. 12. 07:59
반응형

문자열에서 문자 발생 횟수를 어떻게 계산합니까?


나는 문자열이

a.b.c.d

'.'의 발생 횟수를 계산하고 싶습니다. 관용적 방식으로, 바람직하게는 하나의 라이너.

(이전에는 모든 사람들이 루프를 사용하지 않고 대답하려고하는 이유가 궁금한 경우를 대비하여이 제약 조건을 "루프없이"로 표현했습니다.)


이것에 대한 나의 '아이디 오 메틱 원 라이너'는 다음과 같습니다.

int count = StringUtils.countMatches("a.b.c.d", ".");

이미 commons lang 에있을 때 직접 작성하는 이유는 무엇 입니까?

이를위한 Spring Framework의 oneliner는 다음과 같습니다.

int occurance = StringUtils.countOccurrencesOf("a.b.c.d", ".");

이건 어때. 아래에 정규 표현식을 사용하지 않으므로 다른 솔루션보다 빠르며 루프를 사용하지 않습니다.

int count = line.length() - line.replace(".", "").length();

다른 답변과 하나의 라이너를 사용 하여이 작업을 수행하는 모든 방법을 요약하면 다음과 같습니다.

   String testString = "a.b.c.d";

1) Apache Commons 사용

int apache = StringUtils.countMatches(testString, ".");
System.out.println("apache = " + apache);

2) 스프링 프레임 워크 사용

int spring = org.springframework.util.StringUtils.countOccurrencesOf(testString, ".");
System.out.println("spring = " + spring);

3) 바꾸기 사용

int replace = testString.length() - testString.replace(".", "").length();
System.out.println("replace = " + replace);

4) replaceAll 사용 (사례 1)

int replaceAll = testString.replaceAll("[^.]", "").length();
System.out.println("replaceAll = " + replaceAll);

5) replaceAll 사용 (사례 2)

int replaceAllCase2 = testString.length() - testString.replaceAll("\\.", "").length();
System.out.println("replaceAll (second case) = " + replaceAllCase2);

6) 분할 사용

int split = testString.split("\\.",-1).length-1;
System.out.println("split = " + split);

7) Java8 사용 (사례 1)

long java8 = testString.chars().filter(ch -> ch =='.').count();
System.out.println("java8 = " + java8);

8) Java8 (case 2 )을 사용하면 case 1보다 유니 코드에 더 좋습니다.

long java8Case2 = testString.codePoints().filter(ch -> ch =='.').count();
System.out.println("java8 (second case) = " + java8Case2);

9) StringTokenizer 사용

int stringTokenizer = new StringTokenizer(" " +testString + " ", ".").countTokens()-1;
System.out.println("stringTokenizer = " + stringTokenizer);

코멘트에서 : StringTokenizer, abcd의 경우 작동하지만 a ... bc ... d 또는 ... abcd 또는 a .... b ...... c ..... d에주의하십시오. ... 등이 작동하지 않습니다. 그냥 계산됩니다. 한 번만 문자 사이

github의 추가 정보

성능 테스트 ( JMH 사용 , 모드 = AverageTime, 0.010다음보다 우수 0.351) :

Benchmark              Mode  Cnt  Score    Error  Units
1. countMatches        avgt    5  0.010 ±  0.001  us/op
2. countOccurrencesOf  avgt    5  0.010 ±  0.001  us/op
3. stringTokenizer     avgt    5  0.028 ±  0.002  us/op
4. java8_1             avgt    5  0.077 ±  0.005  us/op
5. java8_2             avgt    5  0.078 ±  0.003  us/op
6. split               avgt    5  0.137 ±  0.009  us/op
7. replaceAll_2        avgt    5  0.302 ±  0.047  us/op
8. replace             avgt    5  0.303 ±  0.034  us/op
9. replaceAll_1        avgt    5  0.351 ±  0.045  us/op

조만간 무언가 가 반복되어야합니다. split필요한 것보다 훨씬 강력한 것을 사용하는 것보다 (매우 간단한) 루프를 작성하는 것이 훨씬 간단 합니다.

반드시 루프를 별도의 방법으로 캡슐화하십시오. 예 :

public static int countOccurrences(String haystack, char needle)
{
    int count = 0;
    for (int i=0; i < haystack.length(); i++)
    {
        if (haystack.charAt(i) == needle)
        {
             count++;
        }
    }
    return count;
}

그런 다음 기본 코드에 루프가 필요하지 않지만 루프가 어딘가에 있어야합니다.


나는 Mladen과 비슷한 아이디어를 가지고 있었지만 그 반대는 ...

String s = "a.b.c.d";
int charCount = s.replaceAll("[^.]", "").length();
println(charCount);

String s = "a.b.c.d";
int charCount = s.length() - s.replaceAll("\\.", "").length();

ReplaceAll ( ".")은 모든 문자를 대체합니다.

PhiLho의 솔루션 은 ReplaceAll ( "[^.]", "")을 사용합니다. [.]는 'any character'가 아닌 'dot'문자를 나타내므로 이스케이프 할 필요가 없습니다.


내 '아이디 오 매틱 원 라이너'솔루션 :

int count = "a.b.c.d".length() - "a.b.c.d".replace(".", "").length();

StringUtils를 사용하는 솔루션이 왜 허용되는지 모르십시오.


String s = "a.b.c.d";
long result = s.chars().filter(ch -> ch == '.').count();

더 짧은 예는

String text = "a.b.c.d";
int count = text.split("\\.",-1).length-1;

루프가없는 솔루션은 다음과 같습니다.

public static int countOccurrences(String haystack, char needle, int i){
    return ((i=haystack.indexOf(needle, i)) == -1)?0:1+countOccurrences(haystack, needle, i+1);}


System.out.println("num of dots is "+countOccurrences("a.b.c.d",'.',0));

글쎄, 루프가 있지만 보이지 않습니다 :-)

-요나탄


이 목적을 위해 새 문자열을 할당하는 아이디어가 마음에 들지 않습니다. 그리고 문자열에는 이미 값을 저장하는 char 배열이 있으므로 String.charAt ()은 실제로 무료입니다.

for(int i=0;i<s.length();num+=(s.charAt(i++)==delim?1:0))

J2SE만으로 1 줄 이하로 수집이 필요한 추가 할당없이 트릭을 수행합니다.


자, 요나탄의 솔루션에서 영감을 얻은 것은 순전히 재귀 적입니다. 사용되는 유일한 라이브러리 방법은 length()및이며 charAt(), 어느 것도 반복하지 않습니다.

public static int countOccurrences(String haystack, char needle)
{
    return countOccurrences(haystack, needle, 0);
}

private static int countOccurrences(String haystack, char needle, int index)
{
    if (index >= haystack.length())
    {
        return 0;
    }

    int contribution = haystack.charAt(index) == needle ? 1 : 0;
    return contribution + countOccurrences(haystack, needle, index+1);
}

재귀가 반복으로 계산되는지 여부는 사용하는 정확한 정의에 따라 다르지만 아마도 최대한 가깝습니다.

요즘 대부분의 JVM이 꼬리 재귀를 수행하는지 여부는 알 수 없습니다 ... 그렇지 않으면 적절하게 긴 문자열에 대해 스택 스택 오버플로가 발생합니다.


스택을 날리지 않는 비 루프 버전 인 Jon Skeet에서 영감을 얻었습니다. 포크 조인 프레임 워크를 사용하려는 경우에도 유용한 시작점입니다.

public static int countOccurrences(CharSequeunce haystack, char needle) {
    return countOccurrences(haystack, needle, 0, haystack.length);
}

// Alternatively String.substring/subsequence use to be relatively efficient
//   on most Java library implementations, but isn't any more [2013].
private static int countOccurrences(
    CharSequence haystack, char needle, int start, int end
) {
    if (start == end) {
        return 0;
    } else if (start+1 == end) {
        return haystack.charAt(start) == needle ? 1 : 0;
    } else {
        int mid = (end+start)>>>1; // Watch for integer overflow...
        return
            countOccurrences(haystack, needle, start, mid) +
            countOccurrences(haystack, needle, mid, end);
    }
}

(면책 조항 : 테스트되지 않았으며, 컴파일되지 않았으며, 합리적이지 않습니다.)

아마도 가장 좋은 방법 (단일 스레드, 대리 쌍 지원 없음) :

public static int countOccurrences(String haystack, char needle) {
    int count = 0;
    for (char c : haystack.toCharArray()) {
        if (c == needle) {
           ++count;
        }
    }
    return count;
}

이것의 효율성에 대해서는 확실하지 않지만 타사 라이브러리를 가져 오지 않고 작성할 수있는 가장 짧은 코드입니다.

public static int numberOf(String target, String content)
{
    return (content.split(target).length - 1);
}

함께 당신은이를 달성하기 위해 스트림을 사용할 수 있습니다. 분명히 배후에 반복이 있지만 명시 적으로 작성할 필요는 없습니다!

public static long countOccurences(String s, char c){
    return s.chars().filter(ch -> ch == c).count();
}

countOccurences("a.b.c.d", '.'); //3
countOccurences("hello world", 'l'); //3

Java 8에서 reduce를 사용하여이 문제를 해결할 수도 있습니다.

int res = "abdsd3$asda$asasdd$sadas".chars().reduce(0, (a, c) -> a + (c == '$' ? 1 : 0));
System.out.println(res);

산출:

3

완전한 샘플 :

public class CharacterCounter
{

  public static int countOccurrences(String find, String string)
  {
    int count = 0;
    int indexOf = 0;

    while (indexOf > -1)
    {
      indexOf = string.indexOf(find, indexOf + 1);
      if (indexOf > -1)
        count++;
    }

    return count;
  }
}

요구:

int occurrences = CharacterCounter.countOccurrences("l", "Hello World.");
System.out.println(occurrences); // 3

답변을 얻는 가장 간단한 방법은 다음과 같습니다.

public static void main(String[] args) {
    String string = "a.b.c.d";
    String []splitArray = string.split("\\.",-1);
    System.out.println("No of . chars is : " + (splitArray.length-1));
}

Spring 프레임 워크를 사용하는 경우 "StringUtils"클래스를 사용할 수도 있습니다. 방법은 "countOccurrencesOf"입니다.


split()한 줄의 코드로 함수를 사용할 수 있습니다

int noOccurence=string.split("#",-1).length-1;

public static int countOccurrences(String container, String content){
    int lastIndex, currIndex = 0, occurrences = 0;
    while(true) {
        lastIndex = container.indexOf(content, currIndex);
        if(lastIndex == -1) {
            break;
        }
        currIndex = lastIndex + content.length();
        occurrences++;
    }
    return occurrences;
}

import java.util.Scanner;

class apples {

    public static void main(String args[]) {    
        Scanner bucky = new Scanner(System.in);
        String hello = bucky.nextLine();
        int charCount = hello.length() - hello.replaceAll("e", "").length();
        System.out.println(charCount);
    }
}//      COUNTS NUMBER OF "e" CHAR´s within any string input

메소드가 숨길 수는 있지만 루프 (또는 재귀)없이 계산할 수는 없습니다. 성능상의 이유로 char []를 사용하려고합니다.

public static int count( final String s, final char c ) {
  final char[] chars = s.toCharArray();
  int count = 0;
  for(int i=0; i<chars.length; i++) {
    if (chars[i] == c) {
      count++;
    }
  }
  return count;
}

replaceAll (RE)을 사용하는 것이 가장 좋은 방법은 아닙니다.


코드 어딘가에서 무언가가 반복되어야합니다. 이 문제를 해결할 수있는 유일한 방법은 루프를 완전히 푸는 것입니다.

int numDots = 0;
if (s.charAt(0) == '.') {
    numDots++;
}

if (s.charAt(1) == '.') {
    numDots++;
}


if (s.charAt(2) == '.') {
    numDots++;
}

... 등, 그러나 당신은 그것을 실행하는 컴퓨터 대신 소스 편집기에서 수동으로 루프를 수행하는 사람입니다. 의사 코드를 참조하십시오.

create a project
position = 0
while (not end of string) {
    write check for character at position "position" (see above)
}
write code to output variable "numDots"
compile program
hand in homework
do not think of the loop that your "if"s may have been optimized and compiled to

약간 다른 스타일의 재귀 솔루션이 있습니다.

public static int countOccurrences(String haystack, char needle)
{
    return countOccurrences(haystack, needle, 0);
}

private static int countOccurrences(String haystack, char needle, int accumulator)
{
    if (haystack.length() == 0) return accumulator;
    return countOccurrences(haystack.substring(1), needle, haystack.charAt(0) == needle ? accumulator + 1 : accumulator);
}

캐릭터를 분할 한 다음 결과 배열의 길이를 얻으십시오. 배열 길이는 항상 인스턴스 수 + 1입니다. 맞습니까?


다음 소스 코드는 사용자가 입력 한 단어에서 주어진 문자열의 발생 횟수를 제공합니다.

import java.util.Scanner;

public class CountingOccurences {

    public static void main(String[] args) {

        Scanner inp= new Scanner(System.in);
        String str;
        char ch;
        int count=0;

        System.out.println("Enter the string:");
        str=inp.nextLine();

        while(str.length()>0)
        {
            ch=str.charAt(0);
            int i=0;

            while(str.charAt(i)==ch)
            {
                count =count+i;
                i++;
            }

            str.substring(count);
            System.out.println(ch);
            System.out.println(count);
        }

    }
}

int count = (line.length() - line.replace("str", "").length())/"str".length();

이클립스 컬렉션 사용하기

int count = CharAdapter.adapt("a.b.c.d").count(c -> c == '.');

계산할 문자가 두 개 이상인 경우 CharBag다음과 같이 사용할 수 있습니다 .

CharBag bag = CharAdapter.adapt("a.b.c.d").toBag();
int count = bag.occurrencesOf('.');

참고 : 저는 Eclipse Collections의 커미터입니다.


글쎄, 비슷한 작업 으로이 스레드를 우연히 발견했습니다. 프로그래밍 언어 제한을 보지 못했고 groovy가 java vm에서 실행되기 때문에 Groovy를 사용하여 문제를 해결하는 방법은 다음과 같습니다.

"a.b.c.".count(".")

끝난.

참고 : https://stackoverflow.com/questions/275944/how-do-i-count-the-number-of-occurrences-of-a-char-in-a-string



반응형