首页 文章

如何计算字符串中char的出现次数?

提问于
浏览
459

我有字符串

a.b.c.d

我想计算' . '的出现次数 . 以惯用的方式,最好是单线 .

(以前我把这个约束表达为“没有循环”,如果你想知道为什么每个人都试图回答而不使用循环) .

30 回答

  • 35

    我的'惯用单线'是这样的:

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

    当它已经在commons lang时,为什么要自己写呢?

    Spring Framework的oneliner就是:

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

    这个怎么样 . 它不使用下面的regexp,所以应该比其他一些解决方案更快,并且不会使用循环 .

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

    总结其他答案以及我所知道的使用单线程的所有方法:

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

    1)使用 Apache Commons

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

    2)使用 Spring Framework's

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

    3)使用 replace

    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)使用 split

    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 (情况2),对于unicode可能比情况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);
    

    From comment :小心使用StringTokenizer,对于abcd它可以工作但是对于...... bc ... d或... abcd或者...... b ...... c ..... d . ..等等它不会起作用 . 它只是值得 . 人物之间只有一次

    更多信息github

    Perfomance test(使用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
    
  • 24

    迟早,某些东西必须循环 . 编写(非常简单)循环比使用类似 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;
    }
    

    然后你不需要在主代码中使用循环 - 但循环必须在某处 .

  • 60

    我有一个类似于Mladen的想法,但相反......

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

    ReplaceAll(“ . ”)将替换所有字符 .

    PhiLho's solution使用ReplaceAll("[^.]",“”),它不需要转义,因为[ . ]代表字符'dot',而不是'any character' .

  • 9

    我的'惯用单线'解决方案:

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

    不知道为什么接受使用StringUtils的解决方案 .

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

    一个较短的例子是

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

    这是一个没有循环的解决方案:

    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));
    

    好吧,有一个循环,但它是 invisible :-)

    • Yonatan
  • 167

    我不喜欢为此目的分配新字符串的想法 . 由于字符串后面已经有一个char数组,它存储了它的值,String.charAt()实际上是免费的 .

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

    如果没有需要收集的额外分配,只需要一行或更少,只需要J2SE .

  • 4

    好吧,受到Yonatan 's solution, here'的启发,它纯粹是递归的 - 唯一使用的库方法是 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是否会进行尾递归...如果不是,你会得到适当长串的同名堆栈溢出,当然 .

  • 5

    灵感来自Jon Skeet,一个不会让你的筹码无法破坏的非循环版本 . 如果要使用fork-join框架,也是有用的起点 .

    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;
    }
    
  • 26

    不确定这个效率,但它是我可以编写的最短代码而不引入第三方库:

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

    使用java-8,您还可以使用流来实现此目的 . 显然幕后有一个迭代,但你不必明确地写它!

    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
    
  • 3

    Complete sample:

    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;
      }
    }
    

    Call:

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

    如果您使用的是Spring框架,也可以使用“StringUtils”类 . 该方法将是“countOccurrencesOf” .

  • 2

    获得答案的最简单方法如下:

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

    也可以在Java 8中使用reduce来解决这个问题:

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

    输出:

    3
    
  • 7
    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
    
  • 5

    您只需一行代码即可使用 split() 功能

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

    虽然方法可以隐藏它,但没有循环(或递归)的计数是没有办法的 . 出于性能原因,您希望使用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)听起来不是最好的方式 .

  • 13
    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;
    }
    
  • 4

    在代码中的某个地方,必须循环 . 解决这个问题的唯一方法是完全展开循环:

    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
    
  • 5

    这是一个略有不同的样式递归解决方案:

    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);
    }
    
  • 21

    为什么不拆分字符然后获得结果数组的长度 . 数组长度总是实例数1.对吧?

  • 3

    以下源代码将为您提供用户输入的单词中给定字符串的出现次数: -

    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);
            }
    
        }
    }
    
  • 2
    int count = (line.length() - line.replace("str", "").length())/"str".length();
    
  • 2

    使用Eclipse Collections

    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的提交者 .

  • 646

    好吧,有一个非常相似的任务我偶然发现了这个线程 . 我没有看到任何编程语言限制,因为groovy在java vm上运行:这是我如何使用Groovy解决我的问题 .

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

    完成 .

相关问题