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.
Related
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`)
}
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");
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'));
I am new to javascript still trying to learn things.
I've found a solution to a problem about a function that should generate all combinations of a characters within a string.
I'm trying to figure out:
What is happening inside the loop?
How does the loops execute step by step?
I cannot figure how it reaches to that final output.
I tried for a long time to figure out but I m not sure what happens inside those
loops. I don't understand tho how it gets "ab", "ac". ... together
in the final output and where arrTemp pushes result[x] and char. I saw that the result array is initially empty, then is concatenated with arrTemp.
Here is the code I'm struggling with:
function combString(str){
var lenStr = str.length;
var result = [];
var indexCurrent = 0;
while(indexCurrent < lenStr){
var char = str.charAt(indexCurrent);
var x;
var arrTemp = [char];
for(x in result) {
arrTemp.push(""+result[x]+char);
}
result = result.concat(arrTemp);
indexCurrent++;
}
return result;
}
console.log(combString("abc"));
And this is the output
["a", "b", "ab", "c", "ac", "bc", "abc"]
We can simply achieve it by using 'Slice'
function combinator (s) {
list_of_strings = new Array();
for(i=0;i<s.length;i++) {
for(j=i+1;j<s.length+1;j++) {
list_of_strings.push(s.slice(i, j));
}
}
return list_of_strings;
}
document.write(combinator("dog"));
ok that's pretty simple frist I will comment the code for you and then I will show what is done with a simple string example:
function combString(str){
var lenStr = str.length;
var result = [];
var indexCurrent = 0;
while(indexCurrent < lenStr){ // repeat until indexCurrent equals lenStr, the aim is to browse threw the string
var char = str.charAt(indexCurrent); // select the char at indexCurrent
var x;
var arrTemp = [char];//put the selected char in an array
for(x in result) {
/*Here it's a little bit tricky, array are object, and actually
the indexes of the array are properties which names are includes between 0 and
2³²-2, but they can have other properties like any other object. that's
the reason why you can use a for in loop here which will go threw the
array and perform action on its properties with property name stored in the x variable (actually it is better to use a foreach loop) */
arrTemp.push(""+result[x]+char); /* so here you concat the
value of the current property of result (in the for in loop) with the char
at indexCurrent and you add the concatenation result at the end of arrTemp */
}
result = result.concat(arrTemp); //here you concat result array and arrTemp and assign the concatenation result to result (I know there is a lot of result ahah)
indexCurrent++; //and then you go to the next char in the string and you repeat
}
// when the while loop ends you return result
return result;
}
so let's see an example with this string "abc":
for indexCurrent =0 :
result = [];
char = 'a';
arrayTemp (before for in loop)= ['a'];
arrayTemp (after for in loop)= ['a'];
result = ['a'];
for indexCurrent =1 :
result = ['a'];
char = 'b';
arrayTemp (before for in loop) = ['b'];
arrayTemp (after for in loop) = ['b','ab']
result = ['a', 'b', 'ab'];
for indexCurrent =2 :
result = ['a', 'b', 'ab'];
char = 'c';
arrayTemp (before for in loop) = ['c'];
arrayTemp (after for in loop) = ['c','ac','bc','abc']
result = ['a', 'b', 'ab','c','ac','bc','abc'];
I hope that helped you
Here is the commented code, hopefully it will help you understand!
function combString(str) {
//String length
var lenStr = str.length;
//Initially empty, where the results will be stored
var result = [];
//Currently selected letter
var indexCurrent = 0;
//Looping from 0 to the length of the string
//var char is selecting the character at this index. Ex: "a", then "b", then "c"
while (indexCurrent < lenStr) {
//Get the character at the index position.
var char = str.charAt(indexCurrent);
var x;
var arrTemp = [char];
//For each previous result
for (x in result) {
//Add the current character to the index
arrTemp.push("" + result[x] + char);
/*
* Ex: "abc"
* First round: result is empty, so this code doesn't execute
* Second round: result contains "a". Adds "ab" to the result array
* - Then. result array will contain "a","b" and "ab"
* Third round: result contains "a","b","ab"
* For all of these results, add "c" to the resulting array
* Ex: "ac","bc", "abc"
* - Then add "c"
*/
}
result = result.concat(arrTemp);
//Increment the current index to go to the next character
indexCurrent++;
}
return result;
}
console.log(combString("abc"));
Let's assume input is "ab". Here's how the function works without the loops:
var str = "ab";
var lenStr = str.length;
var result = [];
var indexCurrent = 0;
var char, x, arrTemp;
//first while iteration begins
//indexCurrent === 0
//so char becomes "a"
char = str.charAt(indexCurrent);
//A temp array is created so it can be concatenated to the results array.
arrTemp = [char];
//arrTemp == ["a"]
//for-loop here, but since the result array is empty, it wont execute
//result becomes ["a"]
result = result.concat(arrTemp);
//indexCurrent becomes 1
indexCurrent++;
//second while iteration begins
//indexCurrent === 1
//so char becomes "b"
char = str.charAt(indexCurrent);
arrTemp = [char];
//arrTemp == ["b"]
//For-loop begins, x === 0
//result[x] is the xth (in this case, first) value of the result-array
//the double quotes cast the result as string
//in other words, it says:
//"store at the end of the array arrTemp, as string, the value from index x
//in the array result, plus the character stored in the variable char"
arrTemp.push(""+result[x]+char);
//arrTemp is now ["b", "ab"]
//result only has one item, so for-loop ends
//result becomes ["a", "b", "ab"]
result = result.concat(arrTemp);
//indexCurrent becomes 2
indexCurrent++;
//function returns result
Do note that for-in loops should not be used for iterating over arrays (see here).
Simple use of for loop and while statement to get different combinations.
function combu(s){
var buff = [];
var res = [];
for (i=0;i<s.length;i++){
buff = [s[i]];
var index=0;
while(res[index]){
buff.push(''+res[index]+s[i]);
index++;
}
res = res.concat(buff);
}
return res;
}
combu('abc');
I want to cycle through an array of strings and split those strings on a certain character, and then feed those new strings into an array, ex. take the string "val: key" from the first array and then use a function to retrieve the string from the array and split it on ":" into a new array that would contain ["val","key"]. This is what I have so far, and at the bottom is what is returning when console.log it.
var dict = [];
dict.push("me; pro: myself");
dict.push("labor, laboris; n: work");
dict.push("voco, vocare, vocavi, vocatum; v: call");
function parseDict(arr){
/* parseDict takes a dictionary entry and splits it between its latin part and its part of speech/english translation*/
var dictFinal = [];
arr.toString();
for (i = 0; i < arr.length; i++){
dictFinal[i] += arr[i].split(";");
}
return dictFinal;
}
console.log(parseDict(dict)) prints out
[ 0: "undefinedme; pro: myself"
1: "undefinedlabor, laboris; n: work"
2: "undefinedvoco, vocare, vocavi, vocatum; v: call"
]
Why is it not splitting into two strings on the ";", and why is it returning an undefined value?
It is undefined because you are doing += to an empty array index
dictFinal[i] += arr[i].split(";");
^^
First pass dictFinal[i] is undefined so it is
dictFinal[i] = undefined + arr[i].split(";");
You probably just want
dictFinal[i] = arr[i].split(";");
Use dictFinal.push(...) or dictFinal[i] = ...
Calling arr.toString(); doesn't do much in your case; it simply makes a string from the array which is then expected to be assigned to an variable / returned etc...
var dict = [];
dict.push("me; pro: myself");
dict.push("labor, laboris; n: work");
dict.push("voco, vocare, vocavi, vocatum; v: call");
function parseDict(dict) {
// considered that you know the final length of the final
// length of the array you could use: new Array(dict.length)
var dictFinal = [];
for (i = 0; i < dict.length; i++) {
dictFinal[i] = dict[i].split(";");
}
return dictFinal;
}
console.log(parseDict(dict)); // [["me"," pro: myself"],["labor, laboris"," n: work"],["voco, vocare, vocavi, vocatum"," v: call"]]
+= will try to get whatever is in the variable and concat / add with whatever is on the right side of the equal sign:
var a = 'abc';
a += 'def';
console.log(a); // abcdef
var b = 1;
b += 1;
console.log(b); // 2
// and your's case:
var c; // here c === undefined (your case dictFinal[i] === undefined)
c += 'ABC';
console.log(c); // undefinedABC
var my_array = [1,2,3];
// .toString() is called on the array so the concatenation can happen:
// It would be the same as writing:
// 'my_string' + my_array.toString();
// or 'my_string' + my_array.join(',');
var d = 'my_string' + my_array;
console.log(d); // my_string1,2,3
if you really need the += and would not want to see the 'UNDEFINED', could try:
dictFinal[i] = ((typeof dictFinal[i]!=='undefined') ? dictFinal[i]+arr[i].split(";") : arr[i].split(";"));