Related
I am trying to write a program to order a list of strings by most least frequent characters within the list. For example, if the list was [apple, orange, banana] the letter frequency within the list would be a - 5, n - 3, p - 2, e - 2, l- 1, o - 1, r - 1, g - 1, b - 1. Since orange contains the most least frequent letters, the program would return orange, then apple then banana.
So far I've written the code that orders all the letters in the list by frequency. But I need to apply that to find which string contains the most least frequent letters.
Here is my code:
Map<Character, Integer> elemCount = new LinkedHashMap<>();
for (String word : words)
{
for (int i = 0; i < word.length(); i++)
{
if (elemCount.containsKey(word.charAt(i)))
{
elemCount.put(word.charAt(i), elemCount.get(word.charAt(i)) + 1);
}
else
{
elemCount.put(word.charAt(i), 1);
}
}
}
ArrayList<Character> sortedElems = new ArrayList<>();
elemCount.entrySet().stream().sorted(Collections.reverseOrder
(Map.Entry.comparingByValue())).forEach(entry ->
{
for (int i = 1; i <= entry.getValue(); i++)
{
sortedElems.add(entry.getKey());
}
}
);
System.out.println(sortedElems);
try the below code:
public static void main(String[] args){
List<String> list = new ArrayList<String>();
list.add("apple");
list.add("banana");
list.add("orange");
System.out.println(leastFrequentString(list));
}
private static Set<String> leastFrequentString(List<String> list){
Map<String, Integer> mapStringToFrequency = new HashMap<>();
for(String s:list){
Map<Character, Integer> mapCharacterToFrequency = wordFrequency(s);
int totalScore = 0;
for(Character c:mapCharacterToFrequency.keySet()){
if(mapCharacterToFrequency.get(c)>1){
totalScore+=1;
}
}
mapStringToFrequency.put(s,totalScore);
}
HashMap sortByValue = sortByValue(mapStringToFrequency);
return sortByValue.keySet();
}
private static Map<Character,Integer> wordFrequency(String s){
Map<Character, Integer> mapCharacterToFrequency = new HashMap<Character, Integer>();
for(Character c: s.toCharArray()){
if(mapCharacterToFrequency.containsKey(c)){
int frequency = mapCharacterToFrequency.get(c);
frequency +=1;
mapCharacterToFrequency.replace(c,frequency);
}else{
mapCharacterToFrequency.put(c,1);
}
}
return mapCharacterToFrequency;
}
private static LinkedHashMap<String, Integer> sortByValue(Map<String, Integer> hm)
{
// Create a list from elements of HashMap
List<Map.Entry<String, Integer> > list =
new LinkedList<>(hm.entrySet());
// Sort the list
list.sort(Comparator.comparing(Map.Entry::getValue));
// put data from sorted list to HashMap
LinkedHashMap<String, Integer> temp = new LinkedHashMap<>();
for (Map.Entry<String, Integer> aa : list) {
temp.put(aa.getKey(), aa.getValue());
}
return temp;
}
You can divide the solution to these steps:
Find the least frequent letters. In your fruit example these letters are l, o, r, g, and b - all have frequency 1.
Count how many of these letters are contained in each word: apple has 1, orange has 3, banana has 1
Sort the words according to that count
This is how you can find the least frequent letters. First find the lowest frequency by iterating the elemCount map. Then iterate over the map again to find the letters with the lowest frequency:
int lowestFrequency = ...result from
List<Character> leastFrequentLetters = new ArrayList<>();
for (Map.Entry<Character, Integer> entry : elemCount.entrySet()) {
if (entry.getValue() == lowestFrequency) {
leastFrequentLetters.add(entry.getKey());
}
}
This is how you can count how many of the letters of a given word are in leastFrequentLetters:
int count = 0;
for (char c: word.toCharArray()) {
if (leastFrequentLetters.contains(c)) {
count = count + 1;
}
}
Once you have a method to retrieve or compute this count for each word, you can sort the words by it. Makes sense?
public class Main {
public List<String> sortAccordingly(List<String> unsortedList ) {
List<String> sorted=new ArrayList<>();
Map<String,Integer> freq=new TreeMap();
for(String s:unsortedList) {
Map<Character, Integer> fq = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
if (fq.containsKey(s.charAt(i)))
fq.replace(s.charAt(i), fq.get(s.charAt(i)) + 1);
else
fq.put(s.charAt(i), 1);
}
freq.put(s, Collections.max(fq.values()));
}
Map<String,Integer> sortedOne=freq.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue,(e1,e2)->e1,LinkedHashMap::new));
sortedOne.putAll(freq);
sorted.addAll(sortedOne.keySet());
return sorted;
}
public static void main(String[] args) {
List <String> list=new ArrayList<>();
list.add("apple");
list.add("orange");
list.add("banana");
System.out.println(new Main().sortAccordingly(list));
}
}
You can use comparator
Comparator<String> valueCompare=new Comparator<String>() {
#Override
public int compare(String s, String t1) {
return freq.get(s).compareTo(freq.get(t1));
}
};
instead of
Map<String,Integer> sortedOne=freq.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue,(e1,e2)->e1,LinkedHashMap::new));
after that function will be
public List<String> sortAccordingly(List<String> unsortedList ) {
List<String> sorted=new ArrayList<>();
Map<String,Integer> freq=new TreeMap();
Comparator<String> valueCompare=new Comparator<String>() {
#Override
public int compare(String s, String t1) {
return freq.get(s).compareTo(freq.get(t1));
}
};
for(String s:unsortedList) {
Map<Character, Integer> fq = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
if (fq.containsKey(s.charAt(i)))
fq.replace(s.charAt(i), fq.get(s.charAt(i)) + 1);
else
fq.put(s.charAt(i), 1);
}
freq.put(s, Collections.max(fq.values()));
}
Map<String,Integer> sortedOne=new TreeMap<>(valueCompare);
sortedOne.putAll(freq);
sorted.addAll(sortedOne.keySet());
return sorted;
}
If you have a list as you suggested:
[apple, orange, banana] with letter frequency
a - 5, n - 3, p - 2, e - 2, l- 1, o - 1, r - 1, g - 1, b - 1
As I can see you have already written the code to get these frequencies
Next step is to:
iterate over the list elements -> sum frequencies of each letter for apple, orange and banana -> sort! so you can get them in correct order.
Hope this helps.
I am trying to hold the position of every character (A-Z) from encoded string. I am unable to find out a way to implement it in Java.
Below is one example from C++ which I am trying to rewrite in Java.
map<Character,Integer> enc = new map<Character,Integer>();
for (int i = 0; i < encoded.length(); i++)
{
enc[encoded.charAt(i)] = i;
}
Example below:
I will have a Keyword which is unique e.g., Keyword is NEW.
String will be formed by concatenating KEYWORD+Alphabets(A-Z which are not in the Keyword) e.g., NEWABCDFGHIJKLMOPQRSTUVXYZ (note that N,E and W are not repeated again in the above in the 26-Character string. Finally, I would like to hold the position of every character i.e., A-Z from the above string in bold.
If I'm understanding what youre saying, you want to map each character in a string to its index. However, Maps need a unique key for each entry, so your code wont work directly for strings which contain duplicate characters. Instead of using an Integer for each character, we'll use a List of Integers to store all the indexes which this character appears.
Here's how you would do that in java:
public static void main(String[] args) {
Map<Character, List<Integer>> charMap = new HashMap<>();
String string = "aaabbcdefg";
for (int i = 0; i < string.length(); i++) {
Character c = string.charAt(i);
if (charMap.containsKey(c)) {
List<Integer> positions = charMap.get(c);
positions.add(i);
} else {
charMap.put(c, new ArrayList<>(Arrays.asList(i)));
}
}
for (Character c : charMap.keySet()) {
System.out.print(c + ": ");
charMap.get(c).forEach(System.out::print);
System.out.println();
}
}
output:
a: 012
b: 34
c: 5
d: 6
e: 7
f: 8
g: 9
If you don't want to handle duplicates letters , you can do as follows, it’ll only keep last occurrence for each letter :
Map<Character, Integer> enc = new HashMap<>();
for (int i = 0; i < encoded.length(); i++) {
enc.put(encoded.charAt(i), i);
}
——————-
To handle duplicates char, you can hold them in a List or concatenate them in a String for example (on the second I add a filter operation to remove spaces)
public static void main (String[] args)
{
String str = "AUBU CUDU";
Map<Character, List<Integer>> mapList =
IntStream.range(0, str.length())
.boxed()
.collect(Collectors.toMap(i->str.charAt(i), i->Arrays.asList(i), (la,lb)->{List<Integer>res =new ArrayList<>(la); res.addAll(lb); return res;}));
System.out.println(mapList);
//{ =[4], A=[0], B=[2], C=[5], D=[7], U=[1, 3, 6, 8]}
Map<Character, String> mapString =
IntStream.range(0, str.length())
.boxed()
.filter(i->(""+str.charAt(i)).matches("[\\S]"))
.collect(Collectors.toMap(i->str.charAt(i), i->Integer.toString(i), (sa,sb)-> sa+sb ));
System.out.println(mapString);
//{A=0, B=2, C=5, D=7, U=1368}
}
Code Demo
I have to make a program that does the words frequency from a linkedlist and outputs the result like this :
word, number of occurrences, frequency in percentage
import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
public class Link {
public static void main(String args[]) {
long start = System.currentTimeMillis();
LinkedList<String> list = new LinkedList<String>();
File file = new File("words.txt");
try {
Scanner sc = new Scanner(file);
String words;
while (sc.hasNext()) {
words = sc.next();
words = words.replaceAll("[^a-zA-Z0-9]", "");
words = words.toLowerCase();
words = words.trim();
list.add(words);
}
sc.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Map<String, Integer> frequency = new TreeMap<String, Integer>();
for (String count : list) {
if (frequency.containsKey(count)) {
frequency.put(count, frequency.get(count) + 1);
} else {
frequency.put(count, 1);
}
}
System.out.println(frequency);
long end = System.currentTimeMillis();
System.out.println("\n" + "Duration: " + (end - start) + " ms");
}
}
Output : {a=1, ab=3, abbc=1, asd=2, xyz=1}
What I don't know is how to do the frequency in percentage and ignore the words shorter than 2 caracters. For example "a=1" should be ignored.
Thanks in advance.
First, introduce a double variable to keep track of the total number of occurences. E.g.
double total = 0;
Next is to filter out any String with length() < 2. You can already do this before adding them to your LinkedList.
while (sc.hasNext()) {
words = sc.next();
words = words.replaceAll("[^a-zA-Z0-9]", "");
words = words.toLowerCase();
words = words.trim();
if (words.length() >= 2) list.add(words); //Filter out strings < 2 chars
}
Now, when going through your Strings we should increase the total variable by 1 for each occurence like so;
for (String count : list) {
if (frequency.containsKey(count)) {
frequency.put(count, frequency.get(count) + 1);
} else {
frequency.put(count, 1);
}
total++; //Increase total number of occurences
}
We can then use System.out.printf() to print it all out nicely.
for (Map.Entry<String, Integer> entry: frequency.entrySet()) {
System.out.printf("String: %s \t Occurences: %d \t Percentage: %.2f%%%n", entry.getKey(), entry.getValue(), entry.getValue()/total*100);
}
Note that this will not look nice (the printf statement) once you are working with large Strings, or have a ton of occurences. So optionally you could do the following given that maxLength contains the largest length() of any String in your list and occLength contains the amount of digits of the largest occurence.
for (Map.Entry<String, Integer> entry: frequency.entrySet()) {
System.out.printf("String: %" + maxLength + "s Occurences: %" + occLength + "d Percentage: %.2f%%%n", entry.getKey(), entry.getValue(), entry.getValue()/total*100);
}
Ignore strings with size less than 2 while adding to map step and maintain a legal words counter for calculating percentage.
int legalWords = 0;
for (String count: list) {
if (count.size() >= 2) {
if (frequency.containsKey(count)) {
frequency.put(count, frequency.get(count) + 1);
} else {
frequency.put(count, 1);
}
legalWords++;
}
}
for (Map.Entry < String, String > entry: map.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue() + " " + (entry.getValue() / (double) legalWords) * 100.0 + "%");
}
Note: As the OP question does not provide us with details, let's assume that we will count words of one character but we will not output them.
Seperate your logic from your main class:
class WordStatistics {
private String word;
private long occurrences;
private float frequency;
public WordStatistics(String word){
this.word=word;
}
public WordStatistics calculateOccurrences(List<String> words) {
this.occurrences = words.stream()
.filter(p -> p.equalsIgnoreCase(this.word)).count();
return this;
}
public WordStatistics calculateFrequency(List<String> words) {
this.frequency = (float) this.occurrences / words.size() * 100;
return this;
}
// getters and setters
}
Explanation:
Considering this list of words:
List<String> words = Arrays.asList("Java", "C++", "R", "php", "Java",
"C", "Java", "C#", "C#","Java","R");
Count occurrences of word in words using java 8 Streams API:
words.stream()
.filter(p -> p.equalsIgnoreCase(word)).count();
Calculate word's frequency percentage:
frequency = (float) occurrences / words.size() * 100;
Setting up your words' statistics(Occurrences+Frequency):
List<WordStatistics> wordsStatistics = new LinkedList<WordStatistics>();
words.stream()
.distinct()
.forEach(
word -> wordsStatistics.add(new WordStatistics(word)
.calculateOccurrences(words)
.calculateFrequency(words)));
Output result with ignorance of words of one character:
wordsStatistics
.stream()
.filter(word -> word.getWord().length() > 1)
.forEach(
word -> System.out.printf("Word : %s \t"
+ "Occurences : %d \t"
+ "Frequency : %.2f%% \t\n", word.getWord(),
word.getOccurrences(), word.getFrequency()));
Output:
Word : C# Occurences : 2 Frequency : 18.18%
Word : Java Occurences : 4 Frequency : 36.36%
Word : C++ Occurences : 1 Frequency : 9.09%
Word : php Occurences : 1 Frequency : 9.09%
Use a simple data structure to make this easier.
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class WordCounter {
private int wordTotal;
private Map<String, Integer> wordCount = new HashMap<>();
public WordCounter(List<String> words) {
wordTotal = words.size();
for (String word : words) {
wordCount.put(word, wordCount.getOrDefault(word, 0) + 1);
}
}
public Map<String, Double> getPercentageByWord() {
return wordCount.entrySet()
.stream()
.collect(Collectors.toMap(e -> e.getKey(),
e -> getPercentage(e.getValue())));
}
private double getPercentage(double count) {
return (count / wordTotal) * 100;
}
}
Here's a test that uses it.
#Test
public void testWordCount() {
List<String> words = Arrays.asList("a", "a", "a", "a", "b", "b", "c", "d", "e", "f");
WordCounter counter = new WordCounter(words);
Map<String, Double> results = counter.getPercentageByWord();
assertThat(results).hasSize(6);
assertThat(results).containsEntry("a", 40.0);
assertThat(results).containsEntry("b", 20.0);
assertThat(results).containsEntry("c", 10.0);
assertThat(results).containsEntry("d", 10.0);
assertThat(results).containsEntry("e", 10.0);
assertThat(results).containsEntry("f", 10.0);
}
I want to count the frequency of each word in an ArrayList by the start of the word. e.g [cat, cog, mouse] will mean there are 2 words begining with c and one word begining with m. The code I have works fine but there are 26 letters in the alphabet which will require alot more if s. Is there any other way of doing this?
public static void countAlphabeticalWords(ArrayList<String> arrayList) throws IOException
{
int counta =0, countb=0, countc=0, countd=0,counte=0;
String word = "";
for(int i = 0; i<arrayList.size();i++)
{
word = arrayList.get(i);
if (word.charAt(0) == 'a' || word.charAt(0) == 'A'){ counta++;}
if (word.charAt(0) == 'b' || word.charAt(0) == 'B'){ countb++;}
}
System.out.println("The number of words begining with A are: " + counta);
System.out.println("The number of words begining with B are: " + countb);
}
Use a Map
public static void countAlphabeticalWords(List<String> arrayList) throws IOException {
Map<Character,Integer> counts = new HashMap<Character,Integer>();
String word = "";
for(String word : list) {
Character c = Character.toUpperCase(word.charAt(0));
if (counts.containsKey(c)) {
counts.put(c, counts.get(c) + 1);
}
else {
counts.put(c, 1);
}
}
for (Map.Entry<Character, Integer> entry : counts.entrySet()) {
System.out.println("The number of words begining with " + entry.getKey() + " are: " + entry.getValue());
}
Or use a Map and AtomicInteger (as per Jarrod Roberson)
public static void countAlphabeticalWords(List<String> arrayList) throws IOException {
Map<Character,AtomicInteger> counts = new HashMap<Character,AtomicInteger>();
String word = "";
for(String word : list) {
Character c = Character.toUpperCase(word.charAt(0));
if (counts.containsKey(c)) {
counts.get(c).incrementAndGet();
}
else {
counts.put(c, new AtomicInteger(1));
}
}
for (Map.Entry<Character, AtomicInteger> entry : counts.entrySet()) {
System.out.println("The number of words begining with " + entry.getKey() + " are: " + entry.getValue());
}
Best Practices
Never do list.get(i), use for(element : list) instead. And never use ArrayList in a signature use the Interface List instead so you can change the implemenation.
How about this? Considering that the words start only with [a-zA-Z]:
public static int[] getCount(List<String> arrayList) {
int[] data = new int[26];
final int a = (int) 'a';
for(String s : arrayList) {
data[((int) Character.toLowerCase(s.charAt(0))) - a]++;
}
return data;
}
edit:
Just out of curiosity, I made a very simple test comparing my method and Steph's method with map.
List with 236 items, 10000000 iterations (without printing the result): my code took ~10000ms and Steph's took ~65000ms.
Test: http://pastebin.com/HNBgKFRk
Data: http://pastebin.com/UhCtapZZ
Now, every character can be cast to an integer, representing an ASCII decimal. For example, (int)'a' is 97. 'z''s ASCII decimal is 122. http://www.asciitable.com/
You can create a lookup table for the characters:
int characters = new int[128]
Then in your algorithm's loop use the ASCII decimal as index and increment the value:
word = arrayList.get(i);
characters[word.charAt(0)]++;
In the end, you can print the occurence of the characters:
for (int i = 97; i<=122; i++){
System.out.println(String.format("The number of words beginning with %s are: %d", (char)i, characters[i]));
}
I need to write some kind of loop that can count the frequency of each letter in a string.
For example: "aasjjikkk" would count 2 'a', 1 's', 2 'j', 1 'i', 3 'k'. Ultimately id like these to end up in a map with the character as the key and the count as the value. Any good idea how to do this?
You can use a java Map and map a char to an int. You can then iterate over the characters in the string and check if they have been added to the map, if they have, you can then increment its value.
For example:
Map<Character, Integer> map = new HashMap<Character, Integer>();
String s = "aasjjikkk";
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
Integer val = map.get(c);
if (val != null) {
map.put(c, val + 1);
}
else {
map.put(c, 1);
}
}
At the end you will have a count of all the characters you encountered and you can extract their frequencies from that.
Alternatively, you can use Bozho's solution of using a Multiset and counting the total occurences.
Using the stream API as of JDK-8:
Map<Character, Long> frequency =
str.chars()
.mapToObj(c -> (char)c)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
or if you want the keys as Integers:
Map<Character, Integer> frequency =
str.chars()
.mapToObj(c -> (char)c)
.collect(Collectors.groupingBy(Function.identity(), Collectors.summingInt(c -> 1)));
Another variant:
Map<Character, Integer> frequency =
str.chars()
.mapToObj(c -> (char)c)
.collect(Collectors.toMap(Function.identity(), c -> 1, Math::addExact));
A concise way to do this is:
Map<Character,Integer> frequencies = new HashMap<>();
for (char ch : input.toCharArray())
frequencies.put(ch, frequencies.getOrDefault(ch, 0) + 1);
We use a for-each to loop through every character. The frequencies.getOrDefault() gets value if key is present or returns(as default) its second argument.
You can use a Multiset (from guava). It will give you the count for each object. For example:
Multiset<Character> chars = HashMultiset.create();
for (int i = 0; i < string.length(); i++) {
chars.add(string.charAt(i));
}
Then for each character you can call chars.count('a') and it returns the number of occurrences
Here is another solution, dodgy as it may be.
public char getNumChar(String s) {
char[] c = s.toCharArray();
String alphabet = "abcdefghijklmnopqrstuvwxyz";
int[] countArray = new int[26];
for (char x : c) {
for (int i = 0; i < alphabet.length(); i++) {
if (alphabet.charAt(i) == x) {
countArray[i]++;
}
}
}
java.util.HashMap<Integer, Character> countList = new java.util.HashMap<Integer, Character>();
for (int i = 0; i < 26; i++) {
countList.put(countArray[i], alphabet.charAt(i));
}
java.util.Arrays.sort(countArray);
int max = countArray[25];
return countList.get(max);
}
Since there was no Java 8 solution, thought of posting one. Also, this solution is much neater, readable and concise than some of the other solutions mentioned here.
String string = "aasjjikkk";
Map<Character, Long> characterFrequency = string.chars() // creates an IntStream
.mapToObj(c -> (char) c) // converts the IntStream to Stream<Character>
.collect(Collectors.groupingBy(c -> c, Collectors.counting())); // creates a
// Map<Character, Long>
// where the Long is
// the frequency
Well, two ways come to mind and it depends on your preference:
Sort the array by characters. Then, counting each character becomes trivial. But you will have to make a copy of the array first.
Create another integer array of size 26 (say freq) and str is the array of characters.
for(int i = 0; i < str.length; i ++)
freq[str[i] - 'a'] ++; //Assuming all characters are in lower case
So the number of 'a' 's will be stored at freq[0] and the number of 'z' 's will be at freq[25]
Here is a solution:
Define your own Pair:
public class Pair
{
private char letter;
private int count;
public Pair(char letter, int count)
{
this.letter = letter;
this.count= count;
}
public char getLetter(){return key;}
public int getCount(){return count;}
}
Then you could do:
public static Pair countCharFreq(String s)
{
String temp = s;
java.util.List<Pair> list = new java.util.ArrayList<Pair>();
while(temp.length() != 0)
{
list.add(new Pair(temp.charAt(0), countOccurrences(temp, temp.charAt(0))));
temp.replaceAll("[" + temp.charAt(0) +"]","");
}
}
public static int countOccurrences(String s, char c)
{
int count = 0;
for(int i = 0; i < s.length(); i++)
{
if(s.charAt(i) == c) count++;
}
return count;
}
String s = "aaaabbbbcccddddd";
Map<Character, Integer> map = new HashMap<>();
Using one line in Java8
s.chars().forEach(e->map.put((char)e, map.getOrDefault((char)e, 0) + 1));
You can use a CharAdapter and a CharBag from Eclipse Collections and avoid boxing to Character and Integer.
CharBag bag = Strings.asChars("aasjjikkk").toBag();
Assert.assertEquals(2, bag.occurrencesOf('a'));
Assert.assertEquals(1, bag.occurrencesOf('s'));
Assert.assertEquals(2, bag.occurrencesOf('j'));
Assert.assertEquals(1, bag.occurrencesOf('i'));
Assert.assertEquals(3, bag.occurrencesOf('k'));
Note: I am a committer for Eclipse Collections.
There is one more option and it looks quite nice.
Since java 8 there is new method merge java doc
public static void main(String[] args) {
String s = "aaabbbcca";
Map<Character, Integer> freqMap = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
Character c = s.charAt(i);
freqMap.merge(c, 1, (a, b) -> a + b);
}
freqMap.forEach((k, v) -> System.out.println(k + " and " + v));
}
Or even cleaner with ForEach
for (Character c : s.toCharArray()) {
freqMapSecond.merge(c, 1, Integer::sum);
}
package com.rishi.zava;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
public class ZipString {
public static void main(String arg[]) {
String input = "aaaajjjgggtttssvvkkllaaiiikk";
int len = input.length();
Map<Character, Integer> zip = new HashMap<Character, Integer>();
for (int j = 0; len > j; j++) {
int count = 0;
for (int i = 0; len > i; i++) {
if (input.charAt(j) == input.charAt(i)) {
count++;
}
}
zip.put(input.charAt(j), count);
}
StringBuffer myValue = new StringBuffer();
String myMapKeyValue = "";
for (Entry<Character, Integer> entry : zip.entrySet()) {
myMapKeyValue = Character.toString(entry.getKey()).concat(
Integer.toString(entry.getValue()));
myValue.append(myMapKeyValue);
}
System.out.println(myValue);
}
}
Input = aaaajjjgggtttssvvkkllaaiiikk
Output = a6s2t3v2g3i3j3k4l2
If this does not need to be super-fast just create an array of integers, one integer for each letter (only alphabetic so 2*26 integers? or any binary data possible?). go through the string one char at a time, get the index of the responsible integer (e.g. if you only have alphabetic chars you can have 'A' be at index 0 and get that index by subtracting any 'A' to 'Z' by 'A' just as an example of how you can get reasonably fast indices) and increment the value in that index.
There are various micro-optimizations to make this faster (if necessary).
You can use a Hashtable with each character as the key and the total count becomes the value.
Hashtable<Character,Integer> table = new Hashtable<Character,Integer>();
String str = "aasjjikkk";
for( c in str ) {
if( table.get(c) == null )
table.put(c,1);
else
table.put(c,table.get(c) + 1);
}
for( elem in table ) {
println "elem:" + elem;
}
This is similar to xunil154's answer, except that a string is made a char array and a linked hashmap is used to maintain the insertion order of the characters.
String text = "aasjjikkk";
char[] charArray = text.toCharArray();
Map<Character, Integer> freqList = new LinkedHashMap<Character, Integer>();
for(char key : charArray) {
if(freqList.containsKey(key)) {
freqList.put(key, freqList.get(key) + 1);
} else
freqList.put(key, 1);
}
import java.util.*;
class Charfrequency
{
public static void main(String a[]){
Scanner sc=new Scanner(System.in);
System.out.println("Enter Your String :");
String s1=sc.nextLine();
int count,j=1;
char var='a';
char ch[]=s1.toCharArray();
while(j<=26)
{
count=0;
for(int i=0; i<s1.length(); i++)
{
if(ch[i]==var || ch[i]==var-32)
{
count++;
}
}
if(count>0){
System.out.println("Frequency of "+var+" is "+count);
}
var++;
j++;
}
}
}
The shorted possible code using a HashMap. (With no forceful line saves)
private static Map<Character, Integer> findCharacterFrequency(String str) {
Map<Character, Integer> map = new HashMap<>();
for (char ch : str.toCharArray()) {
/* Using getOrDefault(), since Java1.8 */
map.put(ch, map.getOrDefault(ch, 0) + 1);
}
return map;
}
Please try the given code below, hope it will helpful to you,
import java.util.Scanner;
class String55 {
public static int frequency(String s1,String s2)
{
int count=0;
char ch[]=s1.toCharArray();
char ch1[]=s2.toCharArray();
for (int i=0;i<ch.length-1; i++)
{
int k=i;
int j1=i+1;
int j=0;
int j11=j;
int j2=j+1;
{
while(k<ch.length && j11<ch1.length && ch[k]==ch1[j11])
{
k++;
j11++;
}
int l=k+j1;
int m=j11+j2;
if( l== m)
{
count=1;
count++;
}
}
}
return count;
}
public static void main (String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("enter the pattern");
String s1=sc.next();
System.out.println("enter the String");
String s2=sc.next();
int res=frequency(s1, s2);
System.out.println("FREQUENCY==" +res);
}
}
SAMPLE OUTPUT:
enter the pattern
man
enter the String
dhimanman
FREQUENCY==2
Thank-you.Happy coding.
package com.dipu.string;
import java.util.HashMap;
import java.util.Map;
public class RepetativeCharInString {
public static void main(String[] args) {
String data = "aaabbbcccdddffffrss";
char[] charArray = data.toCharArray();
Map<Character, Integer> map = new HashMap<>();
for (char c : charArray) {
if (map.containsKey(c)) {
map.put(c, map.get(c) + 1);
} else {
map.put(c, 1);
}
}
System.out.println(map);
}
}
*import java.util.ArrayList;
import java.util.Collections;
public class Freq {
public static void main(String[] args) {
// TODO Auto-generated method stub
String temp="zsaaqaaaaaaaabbbbbcc";
List<String> temp1= new ArrayList<String> ();
ArrayList<Integer>freq=new ArrayList<Integer>();
for(int i=0;i<temp.length()-1;i++)
{
temp1.add(Character.toString(temp.charAt(i)));
}
Set<String> uniqset=new HashSet<String>(temp1);
for(String s:uniqset)
{
freq.add(Collections.frequency(temp1, s));
System.out.println(s+" -->>"+Collections.frequency(temp1, s));
}
}
}
------Output-------
a -->>10
b -->>5
c -->>1
q -->>1
s -->>1
z -->>1
Use collections frequency method to count frequency of char*
Uffh. Don't you think this is the simplest solution?
char inputChar = '|';
int freq = "|fd|fdfd|f dfd|fd".replaceAll("[^" + inputChar +"]", "").length();
System.out.println("freq " + freq);
We can use frequency method of Collections class for this.
Split the string into string array. Use HashSet to remove duplicates and check frequency of each object in HashSet using frequency method of Collections
void usingCollections(){
String input = "cuttack";
String [] stringArray = input.split("");
Set<String> s = new HashSet(Arrays.asList(stringArray));
for(String abc : s){
System.out.println (abc + ":"+Collections.frequency(Arrays.asList(stringArray),abc));
}
}
This is more Effective way to count frequency of characters in a string
public class demo {
public static void main(String[] args) {
String s = "babdcwertyuiuygf";
Map<Character, Integer> map = new TreeMap<>();
s.chars().forEach(e->map.put((char)e, map.getOrDefault((char)e, 0) + 1));
StringBuffer myValue = new StringBuffer();
String myMapKeyValue = "";
for (Map.Entry<Character, Integer> entry : map.entrySet()) {
myMapKeyValue = Character.toString(entry.getKey()).concat(
Integer.toString(entry.getValue()));
myValue.append(myMapKeyValue);
}
System.out.println(myValue);
}
}
Another way using map merge method
Map<Character, Integer> map = new HashMap<>();
String s = "aasjjikkk";
for (int i = 0; i < s.length(); i++) {
map.merge(s.charAt(i), 1, (l, r) -> l + r);
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
public class FrequenceyOfCharacters {
public static void main(String[] args) {
System.out.println("Please enter the string to count each character frequencey: ");
Scanner sc=new Scanner(System.in);
String s =sc.nextLine();
String input = s.replaceAll("\\s",""); // To remove space.
frequenceyCount(input);
}
private static void frequenceyCount(String input) {
Map<Character,Integer> hashCount=new HashMap<>();
Character c;
for(int i=0; i<input.length();i++)
{
c =input.charAt(i);
if(hashCount.get(c)!=null){
hashCount.put(c, hashCount.get(c)+1);
}else{
hashCount.put(c, 1);
}
}
Iterator it = hashCount.entrySet().iterator();
System.out.println("char : frequency");
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry)it.next();
System.out.println(pairs.getKey() + " : " + pairs.getValue());
it.remove();
}
}
}
import java.io.FileInputStream;
import java.util.HashSet;
import java.util.Iterator;
public class CountFrequencyOfCharater {
public static void main(String args[]) throws Exception
{
HashSet hs=new HashSet();
String str="hey how are you?";
char arr[]=new char[str.length()];
for(int i=0;i<str.length();i++)
{
arr[i]=str.charAt(i);
}
for(int j=0;j<str.length();j++)
{
int c=0;
for(int k=0;k<str.length();k++)
{
if(arr[j]==arr[k])
c++;
}
hs.add(arr[j]+"="+c+",");
}
Iterator it=hs.iterator();
while(it.hasNext())
{
System.out.print(it.next());
}
}
}
#From C language
#include<stdio.h>`
#include <string.h>`
int main()
{
char s[1000];
int i,j,k,count=0,n;
printf("Enter the string : ");
gets(s);
for(j=0;s[j];j++);
n=j;
printf(" frequency count character in string:\n");
for(i=0;i<n;i++)
{
count=1;
if(s[i])
{
for(j=i+1;j<n;j++)
{
if(s[i]==s[j])
{
count++;
s[j]='\0';
}
}
printf(" '%c' = %d \n",s[i],count);
}
}
return 0;
}