3

I'm trying to count the occurrence of each character in an char array. How many times a specific lower case or upper case letter appears? What would be an effective method as I keep running in circles and into errors?

This is the code I used to populate the array with random characters:

char[] chararray = new char[1000]; 
   for (int i = 0; i < chararray.length; i++) { 
       char c = randomCharacter();
       chararray[i] = c;  
   }//end for  

I've tried creating a second array to count it for both upper and lower case such as, but I'm not sure what to do with it:

int[] counter = new int[52];

Any sort of help would be appreciated it. Thank you.

KingKrypton
  • 65
  • 1
  • 1
  • 5
  • 1
    Are you only concerned with a specific range of characters (e.g. the English alphabet)? – Bobby StJacques Sep 10 '15 at 21:48
  • 1
    You need to check out Java Map class: http://docs.oracle.com/javase/7/docs/api/java/util/Map.html – The Coding Monk Sep 10 '15 at 21:48
  • 2
    Nah. chars are integers. Use an array. It's a lot more efficient. (sorry that was in response to the Map suggestion). – Bobby StJacques Sep 10 '15 at 21:49
  • 1
    Are you familiar with [ASCII](http://www.asciitable.com/)? If you are only concerned with the 52 characters and are guaranteed thats what will be in the input, you could loop over them and add them to the `int[] counter = new int[52]` array you made. If they aren't going to be in that range, you can first check if they are between the characters you are interested and then subtract them to get the index. ASCII values `'A'` = `65`, `'Z'` = `90` and `'a'` = `97`, `'z'` = `122`. – mkobit Sep 10 '15 at 21:49
  • Hey thanks for the response. I am only concerned with characters 'a'-'z' and 'A'-'Z' but I'm counting them together with no gap in between. The ASCII method sounds effective as well will try a little later. Thanks. – KingKrypton Sep 10 '15 at 22:11
  • @mkobit Even if the asker does add a check for A-Za-z, the values are still UTF-16 code units (albeit, in this range, with only one code unit needed for a codepoint). That they are also in the ASCII character set and have the same encoded values in the ASCII encoding is not relevant. – Tom Blodget Sep 10 '15 at 22:33

6 Answers6

2

Here is a relatively straightforward method using Java 8 streams

Character[] charArray = new Character[1000];
IntStream.rand(0, charArray.length)
    .forEach(n -> charArray[n] = randomCharacter());
Map<Character, Long> charCountMap = Arrays.stream(charArray)
    .collect(Collectors.groupingBy(Function.identity(), Collectors.counting());

This leaves you with a map from each character to the number of times it occurs in the array.

Forget efficiency unless you are processing billions of characters a second or you are trying to run it on a digital watch from the 90s.

Puce
  • 37,247
  • 13
  • 80
  • 152
sprinter
  • 27,148
  • 6
  • 47
  • 78
  • time complexcity of this? –  Sep 10 '15 at 22:13
  • @ShivaShinde who cares? It's an array of 1000 characters. OP specifically asked for 'effective'. – sprinter Sep 10 '15 at 22:15
  • Almost a downvote since this is not a suitable answer for the OP and clearly not in the spirit of the question. – Zong Sep 10 '15 at 22:17
  • 1
    @ZongZhengLi really? Could you explain further? I thought this was exactly what OP was after? – sprinter Sep 10 '15 at 22:23
  • the charArray needs to be a Character array though, AFAIK, as streams for char arrays are not supported out-of-the-box. Or you could use something like `new String(charArray).chars().mapToObj(c -> (char) c)` – Puce Sep 10 '15 at 22:23
  • @Puce my code above compiles and runs perfectly. I just tested it with 100 billion random chars (using `Stream.generate`). But I'll add the array construction above to make it clearer. – sprinter Sep 10 '15 at 22:25
  • @sprinter Really? I'm getting "no suitable method found for stream(char[])" – Puce Sep 10 '15 at 22:28
  • Yes I should have made clear a `Character` not a `char` array. – sprinter Sep 10 '15 at 22:29
  • 1
    I'm sure you realize this is useless to a beginner. The only goal here should be to help said beginner understand the solution, not treat it as a code golf exercise. You can't say you really intended to help OP at all with this answer. – Zong Sep 10 '15 at 22:30
  • @ZongZhengLi Learning the APIs is part of the learning process, too, IMHO. – Puce Sep 10 '15 at 22:34
  • 1
    @ZongZhengLi I honestly did intend to help them. My experience is that new students grasp streams just as easily as they grasp traditional iteration because they learn functional programming from the start. – sprinter Sep 10 '15 at 22:37
1

Let's say you're only concerned with English alphabetic characters. The char type in Java is really an integer, so you can use a for loop to loop over ranges, e.g.

for( char c='a'; c<='z'; c++) {
   for( char x : chararry ) {
        if( c == x ) {
           // increment your counter for 'c'
        }
   }
}

Use a similar loop for upper case charcters.

Now it's just a matter of where to store your counters. I'd suggest using an array where each index in the array corresponds to one of your character values. You could write a pretty simple method to translate an ASCII character value to an index between 0-51 for an array.

Bobby StJacques
  • 724
  • 4
  • 9
  • 1
    Well yes, you *could* do it that way, but it's horribly inefficient -- `O(n^2)` when you can do it in `O(n)`. Better to just iterate through the array once, and to compute directly from each `char` the index (if any) of the counter to increment. – John Bollinger Sep 10 '15 at 21:56
  • 1
    @JohnBollinger This isn't O(n^2) since the size of the alphabet doesn't increase with the size of the problem. Even though there are two loops it would still be O(n) or O(nk) where k is the size of the alphabet. – Zong Sep 10 '15 at 22:00
  • 1
    Yes, true. Just suggesting a simple, intuitive brute force solution for a small problem. (O(2nk)) – Bobby StJacques Sep 10 '15 at 22:00
  • @ZongZhengLi, you're quite right. I regretted saying that as soon as I walked away from the computer. I knew someone would call me on it. Nevertheless, a constant factor of 26 times worse performance (or more, depending on which characters are counted) is entirely bad enough. – John Bollinger Sep 10 '15 at 23:35
0
public void count(char[] chararray) {
    Map<Character, Integer> map = new HashMap<>();
    for (Character character : chararray) {
        Integer characterCount = map.get(character);
        if(characterCount == null) {
            characterCount = 0;
        }
        characterCount++;
        map.put(character, characterCount);
    }
    System.out.println(map);
}
outdev
  • 5,249
  • 3
  • 21
  • 38
0
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class CountOccurencesOfLetters {

    public static void main(String[] args) 
    {
        String s=" abhiabhiabhiabhiabhi";
        countOcccurence(s);
    }
    private static void countOcccurence(String input)
    {
        Map<String, Integer> map = new HashMap<String, Integer>();
        String[] tokens =input.split("");
        for (int i = 0; i < tokens.length; i++) 
        {
            String string = tokens[i];
            if(map.containsKey(string))
            {
                int value=map.get(string);
                value++;
                map.put(string, value);
            }
            else
            {
                map.put(string, 1);
            }
        }
        Set<Entry<String,Integer>> entryset = map.entrySet();
        for(Entry<String,Integer> entry: entryset)
        {
            System.out.print(entry.getKey()+entry.getValue());
        }
    }
}
0

There can be many ways to get the desired result. Below is the one way, try it ----

package com.test;

import java.util.HashMap;
import java.util.Map;

public class CharCountInArray {

public static void main(String[] args) {
    char[] arr ;
    arr = new char[]{'a', 'b', 'c', 'a', 'b', 'c', 'd','a', 'b', 'c', 'a', 'b', 'c', 'd','a', 'b', 'c', 'a', 'b', 'c', 'd','a', 'b', 'c', 'a', 'b', 'c', 'd','a', 'b', 'c', 'a', 'b', 'c', 'd'};

    Map<Character, Integer> m = new HashMap<Character, Integer>();

    for(int i = 0; i< arr.length; i++){

        if(m.containsKey(arr[i])){

            m.put(arr[i], m.get(arr[i]) + 1);
        }
        else {
            m.put(arr[i], 1);
        }
    }
    System.out.println(m);
}
}
Arvind Kumar
  • 459
  • 5
  • 21
-1
public class Array_Test {

public static void main(String[] args) {
   char[] c={'a','$','a','f','f','$','d','a','6','f','6','e','r','e','#','y','y','#','a','g','r','g'};
   int char_counter=0;      
   char [] c_distinct=new char[c.length];    
   boolean contains=false;
   int index_counter=0;

      for( int i=0;i<=c.length-1;i++)
      {
          if(i==0)
          {
          c_distinct[index_counter]=c[0];
          index_counter++;
          }
          else
          {
          contains=false;
          for(int k=0;k<=c.length-1;k++)
          {
              for(int f=0;f<=index_counter;f++)
              {
                  if(c_distinct[f]==c[i])
                  contains=true;    
              }                  
          }
          if(contains==false)
          {
              c_distinct[index_counter]=c[i];
              index_counter++;                  
          }
          }
      }

      System.out.println(c);
      System.out.println(c_distinct);

      for(int a=0;a<=index_counter-1;a++)
      {
          char_counter=0;
          for(int b=0;b<=c.length-1;b++)
          {

              if(c_distinct[a]==c[b])
              {
                  char_counter++;
              }
          }
          System.out.println(c_distinct[a]+" "+char_counter);
      }                     
   }
}
Dave2e
  • 22,192
  • 18
  • 42
  • 50
Mayuresh
  • 1
  • 1