This is the fourth article of my attempts to follow Stephen Grider's Udemy course in three different languages.
First I quote todays's question:
--- Directions
Given a string, return the character that is most
commonly used in the string.
--- Examples
maxChar("abcccccccd") === "c"
maxChar("apple 1231111") === "1"
JavaScript:
function maxChar(str) {
const charMap = {};
let max = 0;
let maxChar = '';
for (let char of str) {
if (charMap[char]) {
charMap[char]++
} else {
charMap[char] = 1;
}
}
for (let char in charMap) {
if (charMap[char] > max) {
max = charMap[char];
maxChar = char;
}
}
return maxChar;
}
Stephen rewrites the first for loop as:
for (let char of str) {
charMap[char] = charMap[char] + 1 || 1;
}
This is possible because anObject['nonexistentKey']
returns undefined
, undefined + 1
return NaN
, which is falsy.
Python:
def max_char(str):
char_map = {}
max = 0
max_char = ''
for char in str:
char_map.setdefault(char, 0)
char_map[char] += 1
for char in char_map:
if char_map[char] > max:
max = char_map[char]
max_char = char
return max_char
In Python, you can't just try char_map[char] += 1
as in JS, because it would throw a KeyError if the key doesn't exist yet.
More concisely:
def max_char(str):
char_map = {}
for char in str:
char_map.setdefault(char, 0)
char_map[char] += 1
return max(char_map, key=char_map.get)
Source: https://stackoverflow.com/questions/268272/getting-key-with-maximum-value-in-dictionary
max(char_map, key=char_map.get)
is the same as max(char_map.keys(), key=char_map.get)
.
key=char_map.get
is needed to find the (key, value) tuple pair in the dictionary whose value is the largest. max({'a': 2, 'b': 1})
returns 'b'.
Java:
import java.util.HashMap;
import java.util.Map;
public static char maxChar2(String str) {
Map<Character, Integer> charMap = new HashMap<>();
for (char chr : str.toCharArray()) {
Integer chrCount = charMap.get(chr);
if (chrCount == null) {
chrCount = 0;
}
charMap.put(chr, chrCount + 1);
}
int max = 0;
char maxChar = '\0';
for (Map.Entry<Character, Integer> entry : charMap.entrySet()) {
int value = entry.getValue();
if (value > max) {
max = value;
maxChar = entry.getKey();
}
}
return maxChar;
}
Using Stream:
public static char maxChar(String str) {
Map<Character, Long> charMap = str.chars()
.mapToObj(i -> (char) i)
.collect(Collectors.groupingBy(
c -> c, Collectors.counting()));
return charMap.entrySet().stream()
.collect(Collectors.groupingBy(
Map.Entry::getValue,
TreeMap::new,
Collectors.mapping(
Map.Entry::getKey, Collectors.toList())))
.lastEntry()
.getValue()
.get(0);
}
The return statement can be made simpler:
return charMap.entrySet().stream()
.max(Map.Entry.comparingByValue())
.get()
.getKey();
References:
https://codereview.stackexchange.com/questions/133058/print-max-occurring-character-in-a-string
https://stackoverflow.com/questions/48280361/how-to-count-occurrences-for-each-value-in-multimap-java
https://stackoverflow.com/questions/42060294/using-java8-stream-to-find-the-highest-values-from-map
Top comments (5)
Python could do it even better.
I would have done this that way and using the built in 'max' method for the Counter object
To explain a little bit to non Python dev:
if
s
is a valid chain, I build a Counter object with it, get the list of the n (letter, count) elements, getting the first one and returning only the letter.Step by step:
Wow, this looked enigmatic at first, but I understood how it works. Thank you!
Thank you for the comment!
I learned quite a lot from this code. I really appreciate it. Below is just for my understanding:
Actually we can make it more concise with the way I used above for the
max
function:I like how we can write python like psuedocode with few lines.
count element in an element
=> Counter(s)
Though it can be hard to understand and remember all the shortcuts.