## DEV Community is a community of 846,721 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

tommy-3

Posted on

# Learning Algorithms with JS, Python and Java 4: MaxChar

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

## Discussion (5)

Karolis Ryselis

Python could do it even better.

``````import operator
from collections import Counter

def max_char(s):
c = Counter(s)
try:
return max(c.items(), key=operator.itemgetter(1))[0]
except ValueError:
return ""
``````
Pierre Bouillon

I would have done this that way and using the built in 'max' method for the Counter object

``````from collections import Counter

def max_char(s):
return Counter(s).most_common(1)[0][0] if s else ''
``````

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:

``````s = 'abcccccccd'
Counter(s).most_common(1)        # [('c', 7)]
Counter(s).most_common(1)[0]     # ('c', 7)
Counter(s).most_common(1)[0][0]  # 'c
``````
tommy-3

Wow, this looked enigmatic at first, but I understood how it works. Thank you!

tommy-3

Thank you for the comment!

I learned quite a lot from this code. I really appreciate it. Below is just for my understanding:

``````import operator
from collections import Counter

c = Counter('abbb')
print(c)    # prints: Counter({'b': 3, 'a': 1})
print(c.items())    # prints: dict_items([('a', 1), ('b', 3)])

item = list(c.items())[0]
print(item)    # prints: ('a', 1)
print(item[0])    # prints: a
print(item[1])    # prints: 1

itemgetter_1 = operator.itemgetter(1)
print(itemgetter_1(['x', 'y', 'z']))    # prints: y
print(itemgetter_1(item))    # prints: 1

print(max(c.items(), key=operator.itemgetter(1)))    # prints: ('b', 3)
print(max(c.items(), key=operator.itemgetter(1))[0])    # prints: b
``````

Actually we can make it more concise with the way I used above for the `max` function:

``````import operator
from collections import Counter

def max_char(s):
c = Counter(s)
try:
return max(c, key=c.get)
except ValueError:
return ""
``````
Rattanak Chea

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.