Find unique characters in a string and the count of their occurrences - javascript

I need to count the occurrence of characters in a given string and print out the unique characters and the number of how many times they appeared. So, for example, if I receive a string of 'HELLO' it should print out:
H: 1,
E: 1,
L: 2,
O: 1
This is a much-simplified version of a problem, but the answer should put me in the right direction. How can I approach this problem?
Thank you in advance.

This is more or less what it should look like in order to make it easier it prints it in JSON you can already convert it to String yourself if you want.
function count_occurrence(text = "") {
const array_from_text = text.split("");
const result = {};
Array.from(new Set(array_from_text)).forEach(word => {
const { length } = array_from_text.filter(w => w === word);
result[word] = length;
});
return result;
};
const occurences = count_occurence("HELLO");
console.log(occurences); // {H: 1, E: 1, L: 2, O: 1}

You could use Array.reduce() to get a count of each occurrence in the input word.
We convert the word to an array using the ... operator, then .reduce() to create an object with a property for each unique letter in the word.
const input = 'HELLO';
const result = [...input].reduce((acc, chr) => {
acc[chr] = (acc[chr] || 0) + 1;
return acc;
}, {});
console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }

const countChars = (str) => {
const charCount = {} ;
for (const c of [...str]) {
charCount[c] = (charCount[c] || 0) + 1 ;
}
return charCount ;
}
console.log(countChars('HELLO')) ; // {H: 1, E: 1, L: 2, O: 1}

My approach to this problem is:
let str = "HELLO";
// An object for the final result {character:count}
let counts = {};
// Loop through the str...
for (let index = 0; index < str.length; ++index) {
// Get each char
let ch = str.charAt(index);
// Get the count for that char
let count = counts[ch];
// If we have one, store that count plus one;
if (count) {
counts[ch] += 1;
} else {
// if not, store one
counts[ch] = 1;
}
// or more simply with ternary operator
// counts[ch] = count ? count + 1 : 1;.
}
console.log(counts);

Maybe the easiest answer is just split to char and put it into the map.
const count={}
"HELLO".split("").forEach(e=>{
count[e]??=0;
count[e]++;
})
count is what you want.

Use a dictionary like datastructure that gives you O(1) access and update times. In JS you can use an Object literat (not recommended) or a Map.
Iterate over the characters of your string and update the dictionary by incrementing the character count of the current character. If it isn't in your dictionary add it and set the count to one.
When done with the iteration, iterate over the keys of your dictionary, where the values are the the number of occurence of that specific character, and output them in any format of your liking.
const myStr = "Hello"
const myMap = new Map()
for (let c of myStr) {
if (myMap.has(c)) {
myMap.set(c, myMap.get(c)+1)
} else {
myMap.set(c, 1)
}
}
for (let k of myMap.keys()) {
console.log(`${k} occures ${myMap.get(k)} times`)
}

Related

How to count 3 different vowels

I want to check if my string has 3 different vowels. Mine code below counts every vowel regardless if they are the same.
function hasThreeVowels(str) {
let vowelCount = 0;
let vowels = "aeiou"
for (let char of str) {
if(vowels.includes(char)) {
vowelCount++
}
}
return vowelCount >= 3;
}
You could keep track of the vowels you used and only increase the vowelCount if the vowel is not used yet.
function hasThreeDifferentVowels(str) {
let vowelCount = 0;
let vowels = 'aeiou';
let usedVowels = { a: false, e: false, i: false, o: false, u: false };
for (let char of str) {
if (vowels.includes(char) && !usedVowels[char]) {
vowelCount++;
usedVowels[char] = true;
}
}
return vowelCount >= 3;
}
console.log(hasThreeDifferentVowels('abaacaaeevaa'));
console.log(hasThreeDifferentVowels('abaacaaeevai'));
Please see the code below:
function hasThreeVowels(str) {
let vowelCount = 0;
let vowels = 'aeiou';
let vowelsObj = {
a: 0,
e: 0,
i: 0,
o: 0,
u: 0,
};
for (let char of str) {
if (vowels.includes(char)) {
if (vowelsObj[char] === 0) {
vowelsObj[char] = 1;
vowelCount++;
}
}
}
return vowelCount >= 3;
}
To check if a given string to the hasThreeVowels() has three distinct vowels in it, I would create a vowelsObject with keys being each vowel and values 0. Then after looping through each character of the given string, I will check:
1- If the character is vowel or not
2- If yes, I will check if the value of that vowel in the vowelsObject is 0
3- If yes, I will set the value to be one and increase the counter.
You could define the vowels as a Set (of 5). Then subtract each character from that set and if the set's size reduces to just 2, then you know there have been 3 distinct vowels:
function hasThreeVowels(str) {
const vowels = new Set("aeiou");
return [...str].some(ch => vowels.delete(ch) && vowels.size < 3);
}
console.log(hasThreeVowels('fantastic')); // false
console.log(hasThreeVowels('amazing')); // false
console.log(hasThreeVowels('fabulous')); // true
console.log(hasThreeVowels('awesome')); // true
I find the use of some elegant, but it will run somewhat faster with a for loop.

Count the occurrence of every alphabet from a string in Javascript

I have seen similar questions like this asked before, such as counting characters in a given string. However when it comes to comparing given string to the letters of the alphabet and returning an object with occurences such as:
const letters = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
const sampleString = "a bee";
const results = {
a: 1,
b: 1,
c: 0,
d: 0,
e: 2,
f: 0,
...
}
We can use Array.reduce(),
to count letters in the sampleString.
We start by creating a letterMap to specify all valid letters to be counted.
In the reduce loop, we only increment letters that are present in the letterMap, using the (c in acc) expression.
const letters = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
const sampleString = "a bee";
const letterMap = letters.reduce((acc, c) => {
acc[c] = 0;
return acc;
}, {});
const result = [...sampleString].reduce((acc, c) => {
if (c in acc) acc[c]++;
return acc;
}, letterMap);
console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; top: 0; }
Here's another way, using just one loop, again using Array.reduce(), this assumes we don't wish to count whitespace:
const letters = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
const sampleString = "a bee";
const result = [...letters, ...sampleString].reduce((acc, c) => {
if (c in acc) {
acc[c]++;
} else if (c.trim()) {
acc[c] = 0;
}
return acc;
}, {});
console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; top: 0; }
I like using Object.fromEntries for this:
const sampleString = "a bee";
const result = Object.fromEntries(Array.from("abcdefghijklmnopqrstuvwxyz", ch => [ch, 0]));
for (let ch of sampleString)
if (ch in result) result[ch]++;
console.log(result);
Using Array.reduce and String.match may be an idea. So, for each letter of letters, use match (length) to determine the frequency of the letter in the given sample.
const letters = `abcdefghijklmnopqrstuvwxyz`.split(``);
const freq = (chr, sample) => (sample.match(RegExp(chr, `g`)) || []).length;
const result = letters.reduce( (acc, chr) =>
({...acc, [chr]: freq(chr, acc.sample)}), {sample: "a bee"});
console.log(result);
Or a more undestandable way
const letters = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
const sampleString = "a bee";
results = {};
sampleString.forEach(letter=>{
if(letters.includes(letter)) {
if(results[letter] === undefined) results[letter]=0;
results[letter]++;
}
});
making the value as a key is a bad practice, because it will be hard to read, I recommend to call it what it is:
const letters = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
const tempString = "This is a string.";
let results = []
letters.forEach( char =>{
const count = countCharacterOccurences(tempString, char)
results.push({ alphabet: char, count })
})
function countCharacterOccurences(string, char) {
return string.split(char).length - 1;
}
console.log(results)
//filter alphabet with value
const alphabetWithCount = results.filter( result => {
return result.count > 0
})
console.log(alphabetWithCount)
//log alphabet only with counts
const alphabetOnlyWithCounts = alphabetWithCounts.map( alphabetWithCount => {
return alphabetWithCount.alphabet
})
console.log(alphabetOnlyWithCounts)
//
You can apply .reduce() on the letters directly and in each iteration use RegExp() to replace all letters that do not match the current letter and the count the remaining letters in the string, if any, with .length:
const letters = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];
const sampleString = "a bee";
const results = letters.reduce((result,letter) => ({
...result,
[letter]: sampleString.replace(new RegExp(`[^${letter}]`,'g'), "").length
}), {});
console.log( results );
NOTE:
Please note that:
sr.replace(new RegExp('[^a]','g'), "").length
for example, is equivalent to:
sr.replace(/[^a]/g,"").length
See:
JavaScript: How many times a character occurs in a string?

How can I find out how many of each letter is in a given string?

So I want my code to count the amount of times a letter shows up within a string and output the result.
ie:
amount(door, o) ===> 2
Can I do it using a for loop using
function(amount,letter){
var count=0
for (var i=0 ; i < amount.length ; i++) {
if(amount[i] == letter[i]) count++
}
}
not really sure how to make it work
You can split the string into an array, then loop through each of the letters. We have a letterTracker object, which is where our values are stored. If the key of the letter doesn't exist in the object already, we'll add the key to it. If it does exist, we'll just add one to it.
var countLetters = (string)=>{
const stringArr = string.split('')
let letterTracker = {};
stringArr.forEach(letter=>{
letterTracker[letter]
? letterTracker[letter]++
: letterTracker[letter] = 1
});
return letterTracker;
}
countLetters('wuddup'); //returns { w: 1, u: 2, d: 2, p: 1 }
Using a more ES5 friendly method, and without splitting the string into an array, we can do this (the same result will be achieved):
function countLetters(string){
let letterTracker = {};
for(let i = 0; i < string.length; i++){
if(letterTracker[string[i]]){
letterTracker[string[i]]++
} else {
letterTracker[string[i]] = 1
}
}
return letterTracker;
}
countLetters('wuddupp?'); //returns { w: 1, u: 2, d: 2, p: 2, ?: 1 }
Your code was almost correct but there some mistakes
You have to give the function a name
You have to return count
You have to pass actual strings
You should use let or const instead of var
You should use === instead of ==
function amount(word, letter) {
let count = 0;
for (let i = 0; i < word.length; i++) {
if(word[i] === letter) count++
}
return count;
}
console.log(amount('door', 'o'));
Using array methods you can simplify even more
function amount(word, letter) {
return Array.prototype.reduce.call(word, (acc, el) => acc + (el === letter), 0);
}
console.log(amount('door', 'o'));

Counting vowels in a string JS

What is the best way to count each vowel separately in a string and display it as "A=0", "i=2", "e=1", and so on, case insensitively? I have this so far, but it doesn't count each symbol, only the total amount.
let arr_vowels = 'aeiouAEIOU'.split('');
let count = 0;
word.split('').forEach(function(e) {
if (arr_vowels.indexOf(e) !== -1) {
count++;
}
});
console.log(count);
With the current approach, you are increasing the same count for a vowel.
One approach can be using a Map for example counting each vowel separately, and then loop the entries of the Map to get the key and value.
const vowels = 'aeiouAEIOU';
const str = "This is A test for counting vowels.";
const m = new Map();
for (let i = 0; i < str.length; i++) {
let char = str[i]
if (vowels.includes(char)) {
!m.has(char) ? m.set(char, 1) : m.set(char, m.get(char) + 1);
}
}
for (const [key, value] of m.entries()) {
console.log(`${key} = ${value}`);
}
Similar to the other solution, but simply with an object, you can do the following:
const vowels = {
a: 0,
e: 0,
i: 0,
o: 0,
u: 0,
};
const str = "This is A test for counting vowels.";
str.split('').forEach((letter) => {
const insensitiveLetter = letter.toLowerCase();
if (vowels[insensitiveLetter] !== undefined) {
vowels[insensitiveLetter] += 1;
}
});

Lowercase and Uppercase are the same JS

I am creating a program that will pull up the first non repeated word within a string. While doing this I bump into a logic problem where I need to count a word in uppercase and lowercase the same but still returns the original uppercase version of the string.
Here's my codes:
function firstNonRepeatingLetter(str) {
// split the array and transform it to lowercase
str = str.split('');
// create an obj that will hold the counter of each characters
let myObj = {};
// create a new arr for all the char w/ 1 value
let uniq = [];
// iterate through the splitted array
str.forEach((char) => {
// if the obj contains the same key (char)
if(myObj.hasOwnProperty(char)){
// we add 1 to its value
myObj[char]++;
}else{
// otherwise we set the key value to 1
myObj[char] = 1;
}
});
// check the obj with 1 value,
for(let prop in myObj){
// and then push the key inside a
// new arr with only 1 counter
if(myObj[prop] === 1){
uniq.push(prop);
}
}
console.log(myObj);
// return the first elem in the arr
return uniq.length !== 0 ? uniq[0] : '';
}
firstNonRepeatingLetter('sTress') // => must return 'T' instead return 't'
firstNonRepeatingLetter('NecEssarY') // => must return 'N' instead return 'n'
The object looks like this: { N: 1, e: 1, c: 1, E: 1, s: 2, a: 1, r: 1, Y: 1 }it counts the 'N' and 'n'separately.
Any idea how to retain the actual case without affecting the functionality?
Thanks!
The first way that came to mind is to convert to upper-case for the object property names so that you can count "A" and "a" together, but then in addition to storing the count store the case of the first one found. So within your existing loop:
let upperChar = char.toUpperCase();
if(myObj.hasOwnProperty(upperChar)){
myObj[upperChar].count++; // add 1 to its count
} else {
myObj[upperChar] = { first: char, count: 1 }; // otherwise set count to 1
}
In context with your full code:
function firstNonRepeatingLetter(str) {
str = str.split('');
let myObj = {};
let uniq = [];
str.forEach((char) => {
// if the obj contains the same key (char)
let upperChar = char.toUpperCase();
if(myObj.hasOwnProperty(upperChar)){
myObj[upperChar].count++; // add 1 to its count
}else{
myObj[upperChar] = { first: char, count: 1 }; // otherwise set count to 1
}
});
for(let prop in myObj){ // check the obj with 1 value,
if(myObj[prop].count === 1){ // and then push the key inside a
uniq.push(myObj[prop].first); // new arr with only 1 counter
}
}
console.log(myObj);
return uniq.length !== 0 ? uniq[0] : ''; // return the first elem in the arr
}
console.log(firstNonRepeatingLetter('sTress')); // => must return 'T'
console.log(firstNonRepeatingLetter('NecEssarY')); // => must return 'N'
console.log(firstNonRepeatingLetter('Stress')); // => must return 't'
I suggest you convert the all the characters of the string to either lowercase or uppercase first.
var res = str.toLowerCase();
That way it won't count the characters separately.

Categories

Resources