eman
eman

Reputation: 35

Frequency of elements in an ArrayList

I am trying to write a code that finds the frequency of characters in a String entered in the method (phraseList() is an already working method that takes a word and puts each character in an arrayList) and returns in a new List that has the letters and their frequency, my code below;

public List <String> ltrfrq(String phrase){
List <String> list0 = new ArrayList<String>();
int count = 1;
List <String> list = phraseList(phrase.toUpperCase());
for(int i = 0; i < list.size(); i++){
  for(int j = i + 1; j < list.size(); j++){
    if(list.get(i).equals(list.get(j))){
      count++;
    }
  }
  if(list.get(i).equals(" ")){
    list0.add("Space" + "-" + count);
  }
  else{
    list0.add(list.get(i) + "-" + count);
  }
  count = 1;
}
return list0;
  }
}

My problem however is that it returns all the letters and although I have tried many methods to remove them like using the remove() method, it still does not work, I had something like

list.remove(list.get(i));
i--;

Can anyone help me?

Upvotes: 3

Views: 5000

Answers (4)

Maggie
Maggie

Reputation: 121

HashMap is the easier way to solving this problem. If you have to use List, you can check if the character exist in list0 first. If the character is not exist in list0 then count for its frequency.

Updated Code :

public static void main(String args[]){
    ArrayList <String> list0 = new ArrayList<String>();
        int count = 1;
        //List <String> list = phraseList(phrase.toUpperCase());\
        ArrayList<String> list = new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("a");
        list.add("c");
        list.add("b");
        list.add("a");

        for(int i = 0; i < list.size(); i++){
            boolean isDuplicate = false;
             for (String s: list0){
                 if (s.contains(list.get(i).trim()))
                     isDuplicate =true;
             }

            if (!isDuplicate){

                  for(int j = i + 1; j < list.size(); j++){
                    if(list.get(i).equals(list.get(j))){
                      count++;
                    }
                  }
                  if(list.get(i).equals("/s")){
                    list0.add("Space" + "-" + count);
                  }
                  else{
                    list0.add(list.get(i) + "-" + count);
                  }
                  count = 1;     
            }
        }
        for (String a: list0)
            System.out.println(a);          
}

Upvotes: 1

wwesantos
wwesantos

Reputation: 81

Here is a way to do it using the new method merge() available on Java8 Map.

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

public class CountLetterFrequency {

    public static void main(String[] args) {
        System.out.println(ltrfrq("abacacdea"));
    }

    public static Map<Character, Integer> ltrfrq(String phrase){
        Map<Character, Integer> frqMap = new HashMap<>(); 
        for(int i=0; i<phrase.length(); i++){
            frqMap.merge(phrase.charAt(i), 1, Integer::sum);
        }
        return frqMap;
    }
}

Output:

{a=4, b=1, c=2, d=1, e=1}

With the method merge(), when the item is not in the map, it just adds it, which in this case will add key=charAt(i),value=1. On the other hand, if the key is already on the map, merge calls a function passing both current and new values, and updates the map with the result of this function.

Integer::sum is a method reference, since the merge method expects a function with two parameters, we could rewrite it as (currV,newV) -> currV+newV.

Now, if you wish, you can use the new Stream API instead. First, convert the String to an IntStream, then map each int to a Character, then collect the result on a HashMap and return it. The method ltrfrq would be as follows:

public static Map<Character, Integer> ltrfrq(String phrase){
    return phrase.chars()
        .mapToObj(i->(char)i)
        .collect(HashMap::new,
            (m,k) -> m.merge(k, 1, Integer::sum),
            Map::putAll);
}

Upvotes: 1

user5063151
user5063151

Reputation:

If I could only use List data structures (and my own custom one), this is how I would do it. I would redefine all of the add, remove functions to compensate for duplicate entries.

Output:

[{a=4}, {b=3}, {c=2}, {d=1}]

Code:

import java.util.List;
import java.util.ArrayList;

public class F {

  static class Entry {
    char character;
    int count;

    public Entry(char c, int i) {
      character = c;
      count = i;
    }

    public String toString() {
      return "{" + character + "=" + count + "}";
    }
  }

  public static void main(String[] args) {

    String string = "aaaabbbccd";

    List<Entry> list = frequency(string);

    System.out.println(list);
  }


  public static List<Entry> frequency(String string) {
    int length = string.length();
    char c;
    Entry entry;

    List<Entry> list = new ArrayList<Entry>();

    for (int i = 0; i < length; i++) {
      c = string.charAt(i);

      // add to list
      add(c, list);
    }

    return list;
  }

  public static void add(char c, List<Entry> list) {

    // If the list does not contain the character
    if (!contains(c, list)) {
      list.add(new Entry(c, 1));

    } else {

      // Find the entry
      int index = find(c, list);

      // If we found the entry's indes
      if (index >= 0) {

        // Get the entry
        Entry temp = list.get(index);

        temp.count++;           // Increment its count
        list.remove(index);     // Delete old 1
        list.add(index, temp);  // Insert new 1
      }
    }
  }

  // Finds the index of an entry thats associated with a character
  public static int find(char c, List<Entry> list) {
    int index = -1;
    int length = list.size();


    Entry temp;


    for (int i = 0; i < length; i++) {
      temp = list.get(i);

      if (temp.character == c) {
        index = i;
        break;
      }
    }


    return index;
  }

  // Remove an Entry from list that is associate with a given character
  public static List<Entry> remove(char c, List<Entry> list) {

    for (Entry entry : list) {
      if (entry.character == c) {
        list.remove(entry);
      }
    }

    return list;
  }

  // Get the entry that correlates to a give character in the list
  public static Entry get(char c, List<Entry> list) {
    Entry entryToReturn = null;

    for (Entry entry : list) {
      if (entry.character == c) {
        entryToReturn = entry;
        break;
      }
    }

    return entryToReturn;
  }


  // Checks if the list contains the character
  public static boolean contains(char c, List<Entry> list) {
    boolean contains = false;

    for (Entry entry : list) {
      if (entry.character == c) {
        contains = true;
        break;
      }
    }

    return contains;
  }
}

Upvotes: 2

user5063151
user5063151

Reputation:

HashMaps are key-value pairs. But the keys are unique. So you cannot have duplicate keys. Kind of like a dictionary, you can update the value (definition) of a word, but you won't have that word listed twice.

Watch: https://www.youtube.com/watch?v=j442WG8YzM4

Read: https://beginnersbook.com/2013/12/hashmap-in-java-with-example/

Output:

{a=4, b=3, c=2, d=1}

I'll leave it as an exercise for you to traverse the map.

import java.util.HashMap;

public class F {

  public static void main(String[] args) {

    String string = "aaaabbbccd";

    HashMap<Character, Integer> map = frequency(string);

    System.out.println(map);
  }

  public static HashMap<Character, Integer> frequency(String string) {
    int length = string.length();
    char c;

    HashMap<Character, Integer> map = new HashMap<Character, Integer>();

    for (int i = 0; i < length; i++) {
      c = string.charAt(i);

      if (map.containsKey(c)) {
        map.put(c, map.get(c) + 1);

      } else {

        map.put(c, 1);
      }
    }

    return map;
  }
}

Upvotes: 3

Related Questions