Reputation: 2497
I need help on how can I get not just one but other most common character/letter in a string.
my code only works on getting one of the common character.
but when more than one character are equally common only one are returned. I would like it to return two character if two character are common.
const x = mostCommonCharacter("abbbcddefffg");
console.log(x); // result is *b*
if b and f are most common I would like to return bf
function mostCommonCharacter(str) {
const charHolder = {}; // { a: 1, b: 3, c: 1, d: 2, e: 1, f: 3, g: 1 }
str
.toLowerCase()
.split("")
.forEach(char => {
if (char != " ") {
if (charHolder[char] == null) {
charHolder[char] = 1;
} else {
charHolder[char] += 1;
}
}
});
let highest_num = 0;
let letter = "";
for (const key in charHolder) {
if (charHolder[key] > highest_num) {
highest_num = charHolder[key];
letter = key;
}
}
return letter;
}
but It only return one most common character which is "b"
what I need is for it to return "b" and "f" because both of them are most common. and not just b is there a way to do this?
Upvotes: 2
Views: 2363
Reputation: 1592
A solution involving an algorithmic approach using hashmaps
.
var a = 'abbbcddefffg';
const counter = (str) => {
var ch = {};
for(var i=0; i<str.length;i++) {
if(str[i] in ch) {
ch[str[i]] += 1
} else {
ch[str[i]] = 1
}
}
return ch;
}
let sorted = (list) => Object.fromEntries(Object.entries(list).sort( (a,b) => b[1] - a[1] ))
let counterInSorted = sorted(counter(a));
let getXMostOccuring = (stringObj, x) => {
return Object.keys(stringObj).slice(0,x).join('');
}
console.log('First x elements occuring frequently');
console.log(getXMostOccuring(counterInSorted,2));
console.log(sorted(counter(a)))
This approach will provide with the frequency of each character in a sorted manner. You can now decide to get 'x' most occurring characters.
Upvotes: 0
Reputation: 16908
Please find a more compact approach where you can use Array.prototype.reduce
to get the {letter: frequency} map in an object from the string after splitting it into an array.
Then use the Object.entries
to get the most frequent and second frequent letters after sorting the entries of [key, values]:
const x = mostCommonCharacter("abbbcddefffg");
function mostCommonCharacter(str){
const dict = str.split("").reduce((acc, ele) =>{
acc[ele] = (acc[ele] || 0) + 1;
return acc;
}, {});
const letters = Object.entries(dict).sort((a, b) => b[1] - a[1]).map(a => a[0]);
return letters.length > 1 ? letters.slice(0, 2).join("") : letters.length > 0 ? letters[0] : null;
}
console.log(x);
Upvotes: 0
Reputation: 1255
You could accomplish this with a simple change. Just add the letter to "letters" if it is equal to "highest_num".
let highest_num = 0;
let letters = "";
for (const key in charHolder) {
if (charHolder[key] > highest_num) {
highest_num = charHolder[key];
letters = key;
} else if (charHolder[key] === highest_num) {
letters += key;
}
}
Upvotes: 1
Reputation: 36574
Get the highest_num
and then again iterate through object and get those letters for which count is equal to highest_num
function mostCommonCharacter(str) {
const charHolder = {}; // { a: 1, b: 3, c: 1, d: 2, e: 1, f: 3, g: 1 }
str
.toLowerCase()
.split("")
.forEach(char => {
if (char != " ") {
if (charHolder[char] == null) {
charHolder[char] = 1;
} else {
charHolder[char] += 1;
}
}
});
let highest_num = 0;
for (const key in charHolder) {
if (charHolder[key] > highest_num) {
highest_num = charHolder[key];
}
}
let res = '';
for(let k in charHolder){
if(charHolder[k] === highest_num){
res += k;
}
}
return res;
}
console.log(mostCommonCharacter("abbbcddefffg"))
A shorter version of the code can be obtained by using reduce()
and Math.max
function mostCommonCharacter(str) {
const charHolder = str
.toLowerCase()
.split('')
.reduce((ac,a) => (ac[a] = ac[a] + 1 || 1, ac), {});
let max = Math.max(...Object.values(charHolder));
return Object.entries(charHolder).reduce((ac,[k,v]) =>v === max ? ac + k : ac, '');
}
console.log(mostCommonCharacter("abbbcddefffg"))
Upvotes: 1