How to check how many times character from string appears? - javascript

I want to count how many times each letter from params appears in this string. What am I doing wrong?
function solution(word) {
let temp = {}
for(const c of word) {
temp[c]++;
console.log(temp[c])
}
}
solution("PAPAYA")
It should output me numbers below for each letter, but i keep getting NaN
1 // P appeared once
1 // A appeared once
2 // P appeared second time
2 // A appeaed second time
1 // Y Once
3 // A appeared third time
so it should look like
{
A: 3,
P: 2,
Y: 1
}

Here is an easy solution without changing your code to much
function solution(word) {
let temp = {}
for(const c of word) {
if (temp[c] === undefined)
temp[c] = 1;
else temp[c]++;
}
console.log(temp)
}
solution("PAPAYA")

At the start, no properties are set on the object, so accessing the value for a character results in undefined. Incrementing that produces NaN. You will need to specifically handle that case for the first time a letter appears.
function solution(word) {
let temp = {}
for(const c of word)
temp[c] = (temp[c] || 0) + 1;
return temp;
}
console.log(solution("PAPAYA"));

Easy solution using short-circuit in javascript:
function solution(word) {
let temp = {}
for(const c of word) {
temp[c] = temp[c]+1 || 1;
}
console.log(temp);
}
solution("PAPAYA")
The issue with your solution is that the first time the value is undefined so you were increasing undefined by 1, that's why you were getting NaN (Not A Number).
short-circuit will solve that, if it is not defined, start counting from one

set temp[c] to a number (0) first
for example
if (NaN(temp[c])) temp[c] = 0
The reason for this is because if you do ++ on undefined, it is still undefined, and therefore, not a number

const solution = (str) => {
const result = {}
str.split('').forEach(letter => {
result[letter] = result[letter] ? result[letter] + 1 : 1
})
return result
}
console.log(solution("PAPAYA"))

Simplest solution
function solution(word) {
let temp = {}
for(const c of word) {
if(c in temp)
temp[c]++;
else temp[c] = 1;
}
}
solution("PAPAYA")

Solution
let counter = str => {
return str.split('').reduce((total, letter) => {
total[letter] ? total[letter]++ : total[letter] = 1;
return total;
}, {});
};
console.log(counter("PAPAYA"));
//count
let unordered = counter("PAPAYA");
//sort the count object
const ordered = Object.keys(unordered).sort().reduce(
(obj, key) => {
obj[key] = unordered[key];
return obj;
},
{}
);
console.log(ordered);

function solution(word) {
let charMap = {};
word.split("").forEach((eachChar) => {
if (!charMap[eachChar]) {
charMap[eachChar] = 1;
} else {
charMap[eachChar] += 1;
}
});
console.log(charMap);
return charMap;
}
solution("ppiiyaaallll");

Related

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

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`)
}

Return true if the string in the first element of the array contains all of the letters of the string in the second element

I tried to do this by resetting loop going trough firstword every time its letter matches with secondword letter.
function mutation(arr) {
var compare = [];
var firstword = arr[0].toLowerCase();
var secondword = arr[1].toLowerCase();
var j = 0;
for (let i = 0; i < firstword.length; i++) {
if (firstword[i] === secondword[j]) {
compare.push(secondword[i]);
i = -1;
j++;
}
}
let result = compare.join("")
if (result.length === secondword.length) {
return true;
} else {
return false;
}
}
console.log(mutation(["Noel", "Ole"]));
It works in some cases but in others, like above example, it doesn't. What seems to be the problem?
You need to compare.push(secondword[j]) instead of compare.push(secondword[i])
function mutation(arr) {
var compare = [];
var firstword = arr[0].toLowerCase();
var secondword = arr[1].toLowerCase();
var j = 0;
for (let i = 0; i < firstword.length; i++) {
if (firstword[i] === secondword[j]) {
compare.push(secondword[j]); // Correction here
i = -1;
j++;
}
}
let result = compare.join("");
if (result.length === secondword.length) {
return true;
} else {
return false;
}
}
console.log(mutation(["Noel", "Ole"]));
Also, you can consider using Array.prototype.every.
const mutation = ([first, sec]) => {
const lowerCaseFirst = first.toLowerCase();
const lowerCaseSec = sec.toLowerCase();
return Array.from(lowerCaseSec).every((ch) => lowerCaseFirst.includes(ch));
};
console.log(mutation(["Noel", "Ole"]));
If the strings are small then String.prototype.includes works fine but if they are large then you should consider using a Set.
const mutation = ([first, sec]) => {
const firstSet = new Set(first.toLowerCase());
const lowerCaseSec = sec.toLowerCase();
return Array.from(lowerCaseSec).every((ch) => firstSet.has(ch));
};
console.log(mutation(["Noel", "Ole"]));
Simple ES6 Function, we check with .every() if every characters of secondword is includes inside firstword. It return true if it does.
function mutation(arr) {
const firstword = arr[0].toLowerCase();
const secondword = arr[1].toLowerCase();
return secondword.split('').every(char => firstword.includes(char));
}
console.log(mutation(["Noel", "Ole"]));
The use of Set in SSM's answer works if you don't need to account for duplicate characters in the second string. If you do, here's an implementation that uses a Map of character counts. The map key is the character from string 1 and the value is the number of occurrences. For instance, if you want ["Noel", "Ole"] to return true, but ["Noel", "Olle"] to return false (string 1 does not contain 2 "l" characters). String 2 is then iterated through and character counts decremented if they exist. As soon as a character is not present or the count falls below 1 in the map, the function returns false.
function mutation(arr: string[]): boolean {
return s1ContainsAllCharsInS2(arr[0].toLowerCase(), arr[1].toLowerCase());
}
function s1ContainsAllCharsInS2(s1: string, s2: string): boolean {
if (s2.length > s1.length) {
return false;
}
let charCountMap: Map<string, number> = new Map<string, number>();
Array.from(s1).forEach(c => {
let currentCharCount: number = charCountMap.get(c);
charCountMap.set(c, 1 + (currentCharCount ? currentCharCount : 0));
});
return !Array.from(s2).some(c => {
let currentCharCount: number = charCountMap.get(c);
if (!currentCharCount || currentCharCount < 1){
return true;
}
charCountMap.set(c, currentCharCount - 1);
});
}
A different approach.
Mapping the characters and comparing against that map.
function mutation(arr) {
const chars = {};
for (let char of arr[0].toLowerCase()) {
chars[char] = true;
}
for (let char of arr[1].toLowerCase()) {
if (!chars[char]) {
return false;
}
}
return true;
}
console.log(mutation(["Noel", "Ole"]));
console.log(mutation(["Noel", "Oleeeeeeeeeeeee"]));
If the count also matters (your code doesn't take it into account) you can count the number of occurrences of each character and comparing these counts.
function mutation(arr) {
const chars = {};
for (let char of arr[0].toLowerCase()) {
chars[char] = (chars[char] || 0) + 1;
}
for (let char of arr[1].toLowerCase()) {
// check if chars[char] contains a (not empty == positive) count
// then decrement it for future checks
if (!chars[char]--) {
return false;
}
}
return true;
}
console.log(mutation(["Noel", "Ole"]));
console.log(mutation(["Noel", "Oleeeeeeeeeeeee"]));

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'));

Solving a Permutations problem with Heap's Algorithm in Javascript

I'm working through some "Kata's" on CodeWars.com, and am stuck on the Permutations problem.
Here is the problem: n this kata you have to create all permutations
of an input string and remove duplicates, if present. This means, you
have to shuffle all letters from the input in all possible orders.
Examples:
permutations('a'); // ['a']
permutations('ab'); // ['ab', 'ba']
permutations('aabb'); // ['aabb', 'abab', 'abba', 'baab', 'baba', 'bbaa']
The order of the permutations doesn't matter.
Here is my solution:
function permutations(string) {
const swap = (string, x, y) => {
const stringArray = string.split('')
const swapVar = stringArray[x]
stringArray[x] = stringArray[y]
stringArray[y] = swapVar
return stringArray.join('')
}
const permutate = (k, arr) => {
if (k === 1) {
return arr
} else {
for (let i = 0; i < k - 1; i++) {
if (k % 2 === 0) {
arr.push(swap(string, i, k-1))
} else {
arr.push(swap(string, 0, k-1))
}
}
permutate(k - 1, arr)
}
}
return permutate(string.length, [string])
}
When you pass in a single letter, it works fine. Two letters and it returns undefined. I've console logged the if statement block with the return and it should be returning the correct answer, but the result is still undefined. Considering it's getting the correct answer in the if statement and isn't progressing into the else block, I'm at a loss for why this isn't working.
Thank you in advance!
I figured it out - I was missing the return statement before the recursive function call.
Here is a basic solution
String.prototype.replaceAt = function(index, replacement) {
return this.substr(0, index) + replacement + this.substr(index +
replacement.length);}
var words = [];
var string = "lyes";
for(var i = 0;i< string.length;i++){
for(var j = 0;j<string.length;j++){
var tempChar;
if(i!==j){
tempChar = string[j]
var str = string.replaceAt(j,string[i])
str = str.replaceAt(i,tempChar)
if(!words.includes(str)){
words.push(str)
console.log(str)
}
}
}
}
console.log(words.length +" words found")

array_count_values for JavaScript instead

I have the following PHP-script, now I need to do the same thing in JavaScript. Is there a function in JavaScript that works similar to the PHP function, I have been searching for days but cannot find anything similar? What I want to do is to count the number of times a certain word is being used in an array.
$interfaceA = array($interfaceA_1,$interfaceA_2,$interfaceA_3,$interfaceA_4,$interfaceA_5,$interfaceA_6,$interfaceA_7,$interfaceA_8);
$interfaceA_array=array_count_values($interfaceA);
$knappsatsA = $interfaceA_array[gui_knappsats];
$touchpanelA = $interfaceA_array[gui_touchpanel];
Why not simply create a new javascript array "counts"
Iterate over original array, and increament the count of "counts" for keys encountered in the array.
http://jsfiddle.net/4t28P/1/
var myCurrentArray = new Array("apple","banana","apple","orange","banana","apple");
var counts = {};
for(var i=0;i< myCurrentArray.length;i++)
{
var key = myCurrentArray[i];
counts[key] = (counts[key])? counts[key] + 1 : 1 ;
}
alert(counts['apple']);
alert(counts['banana']);
Another elegant solution would be to use Array.prototype.reduce.
Given:
var arr = new Array("apple","banana","apple","orange","banana","apple");
You can just run reduce on it:
var groups =
arr.reduce(function(acc,e){acc[e] = (e in acc ? acc[e]+1 : 1); return acc}, {});
Finally you can check the result:
groups['apple'];
groups['banana'];
In the sample above reduce takes two parameters:
a function (anonymous here) taking an accumulator (initialized from the second argument of reduce), and the current array element
the initial value of the accumulator
Whatever the function returns, it will be used as the accumulator value in the next call.
From a type perspective, whatever the type of the array elements, the type of the accumulator must match the type of the second argument of reduce (initial value), and the type of the return value of the anonymous function.
This will also be the type of the return value of reduce.
Try
a.reduce((a,c)=> (a[c]=++a[c]||1,a) ,{});
let a= ["apple","banana","apple","orange","banana","apple"];
let count= a.reduce((a,c)=> (a[c]=++a[c]||1,a) ,{});
console.log(count);
How about this:
function arrayCountValues (arr) {
var v, freqs = {};
// for each v in the array increment the frequency count in the table
for (var i = arr.length; i--; ) {
v = arr[i];
if (freqs[v]) freqs[v] += 1;
else freqs[v] = 1;
}
// return the frequency table
return freqs;
}
let snippet = "HARRY POTTER IS A SERIES OF FANTASY NOVELS WRITTEN BY BRITISH AUTHOR J. K. ROWLING. THE NOVELS CHRONICLE" +
" THE LIVES OF A YOUNG WIZARD, HARRY POTTER , AND HIS FRIENDS HERMIONE GRANGER AND RON WEASLEY, ALL OF WHOM ARE " +
" STUDENTS AT HOGWARTS SCHOOL OF WITCHCRAFT AND WIZARDRY";
String.prototype.groupByWord = function () {
let group = {};
this.split(" ").forEach(word => {
if (group[word]) {
group[word] = group[word] + 1;
} else {
group[word] = 1;
}
});
return group;
};
let groupOfWordsByCount = snippet.groupByWord();
console.log(JSON.stringify(groupOfWordsByCount,null, 4))
This should work
function array_count_values(array) {
var tmpArr = {};
var key = '';
var t = '';
var _countValue = function(tmpArr, value) {
if (typeof value === 'number') {
if (Math.floor(value) !== value) {
return;
}
} else if (typeof value !== 'string') {
return;
}
if (value in tmpArr && tmpArr.hasOwnProperty(value)) {
++tmpArr[value];
} else {
tmpArr[value] = 1;
}
}
for (key in array) {
if (array.hasOwnProperty(key)) {
_countValue.call(this, tmpArr, array[key]);
}
}
return tmpArr;
}
console.log(array_count_values([12, 43, 12, 43, "null", "null"]));

Categories

Resources