Increment operator returns NaN - javascript

I am trying to increment a variable using the ++ operator but I keep getting NaN as a result and I'm not sure why. Here is my code:
var wordCounts = { };
var x = 0
var compare = "groove is in the heart";
var words = compare.split(/\b/);
for(var i = 1; i < words.length; i++){
if(words[i].length > 2){
wordCounts["_" + words[i]]++;
}
}
alert(wordCounts.toSource());

The value of wordCounts["_" + words[i]] is initially undefined so when you ++ it, it gives you NaN. Just change your code to:
if (wordCounts["_" + words[i]]) {
wordCounts["_" + words[i]]++;
} else {
wordCounts["_" + words[i]] = 1;
}

Try something like...
var key = "_" + words[i];
if (wordCounts[key]) {
wordCounts[key]++
} else {
wordCounts[key] = 1;
}
You are trying to increment undefined which is giving you NaN.

To be able to use the ++ operator (which takes a number and increments it by one) the target needs to have a number first.
Attempt a check to see if the object is defined, and if not initialize it by setting it's value to 1.
if ('undefined' === typeof wordCounts["_" + words[i]]) {
wordCounts["_" + words[i]] = 0;
}
Something like:
var wordCounts = {};
var x = 0
var compare = "groove is in the heart";
var words = compare.split(/\b/);
for (var i = 1; i < words.length; i++) {
if ('undefined' === typeof wordCounts["_" + words[i]]) {
wordCounts["_" + words[i]] = 0;
}
if (words[i].length > 2) {
wordCounts["_" + words[i]]++;
}
}
alert( JSON.stringify( wordCounts ) );

What you're basically doing is
undefined++
Which will result in...
NaN
Try...
wordCounts["_" + words[i]] = (wordCounts["_" + words[i]]++ || 1);
Since NaN is a "falsey" value the || will fall back to 1.

You're trying to increment an object (wordCounts[]++) it's not a number so it can't be incremented, which is why you're getting that error. What are you actually trying to do (in plain English)?

Related

Counting the occurrence of chars in a javascript string

I have written down code to calculate the count of each of the character in a string.
It seems to be working correctly for some of the words where as for some it fails.
It fails for the last character, as I see the length of the string becomes smaller than the iteration count (but for some of the words)
var str1 = "america"
function noofchars(str1) {
for (var m = 0; m < str1.length + 1; m++) {
var countno = 1;
if (m != 0) {
str1 = str1.slice(1)
}
str2 = str1.substr(0, 1)
for (var i = 0; i < str1.length; i++) {
if (str2 === str1.charAt(i + 1)) {
countno += 1
str1 = str1.slice(0, i + 1) + str1.slice(i + 2) + " "
}
}
console.log(str1.charAt(0) + "=" + countno)
}
}
var findnoofchar = noofchars(str1)
It passes for london, philadelphia, sears, happy
But fails for america, chicago etc
london = l=1, o=2, n=2, d=1
It'd be easier to use an object. First reduce into character counts, then iterate through the key/value pairs and console.log:
function noofchars(str1) {
let r = [...str1].reduce((a, c) => (a[c] = (a[c] || 0) + 1, a), {});
Object.entries(r).forEach(([k, v]) => console.log(`${k}=${v}`));
}
noofchars("america");
ES5 syntax:
function noofchars(str1) {
var r = str1.split("").reduce(function(a, c) {
a[c] = (a[c] || 0) + 1;
return a;
}, {});
Object.keys(r).forEach(function(k) {
console.log(k + "=" + r[k]);
});
}
noofchars("america");
It's easier to understand what reduce is doing in the above snippet.
First, we take a function with two parameters a and c. These can be called anything, I just use a and c for the accumulator and the current item.
Now, the second line:
a[c] = (a[c] || 0) + 1;
This is kind hard, so let's break it down. First let's look at what's in the parentheses:
a[c] || 0
This checks if a has a key/value pair with the key c (as in, the value of c, not the key literally being c). If that doesn't exist, it returns 0. So if a[c] exists, save it as the value of the expression, otherwise use 0.
Now, we add 1, to increment the value.
Finally, we assign the result to a[c]. So if a contained c, the value of a[c] would be incremented. If a didn't contain c, the value of a[c] would be 1.
Then, we return a to be used in the next iteration of reduce.
In the next line:
}, {});
We assign a default value for a. If we didn't do this, the first time reduce ran, a would be "a", and c would be "m" (the first two characters of america). This way, a is {} (an empty object), and c is "a". If we didn't have this second argument, our function wouldn't work.
In this line:
Object.keys(r).forEach(function(k) {...});
We're getting an array of all the keys in r, and looping through them with forEach, with k being the key.
Then, we're logging k (the key), then an equals sign =, then the value of r[k].
You can split the string by each character and then count the number of occurrence of each character by reduce function as below
function noofchars(str1) {
const chArray = str1.split('');
return chArray.reduce(function(acc, ch) {
if (acc[ch]) {
acc[ch]++;
} else {
acc[ch] = 1;
}
return acc;
}, {});
}
var str1 = "america";
var findnoofchar = noofchars(str1);
console.log(findnoofchar);
In your solution you are mutating str1 in this line
str1 = str1.slice(0, i + 1) + str1.slice(i + 2) + " "
which actually changes the length of the string and also checking str1.length in the first loop. In you case you can take the length in the first place. Working version of your code snippet is here
var str1 = "america"
function noofchars(str1) {
const len = str1.length;
for (var m = 0; m < len; m++) {
var countno = 1;
if (m !== 0) {
str1 = str1.slice(1)
}
if (str1.charAt(0) === ' ') {
break;
}
str2 = str1.substr(0, 1)
for (var i = 0; i < str1.length; i++) {
if (str2 === str1.charAt(i + 1)) {
countno += 1
str1 = str1.slice(0, i + 1) + str1.slice(i + 2) + " "
}
}
console.log(str1.charAt(0) + "=" + countno)
}
}
var findnoofchar = noofchars(str1)
Not really knowing what you are trying to accomplish with your code, one solution is to utilize the charAt and Set functions. CharAt is a more direct way to iterate over the string and the Set function eliminates duplicate characters from the set automatically.
var str1 = "america";
function noofchars(str1) {
var charList = new Set();
for (var m = 0; m < str1.length; m++) {
var charX = str1.charAt(m).substr(0, 1);
var countno = 1;
for (var i = 0; i < str1.length; i++) {
if (str1.slice(0, i + 1) == charX) {
countno++;
}
charList.add(charX + "=" + countno);
}
}
// you may need to expand set on Chrome console
console.log(charList);
// a hack to display more easily display on your screen
var listOnScreen = Array.from(charList);
document.getElementById('displaySet').innerHTML=listOnScreen;
}
noofchars(str1);
<div id="displaySet"></div>

Manually remove whitespace in String - JavaScript

I have attempted to make an algorithm that will do the same thing as this function: var string= string.split(' ').join('');
So if I have the following String: Hello how are you it becomes Hellohowareyou
I don't want to use .replace or regex or .split
However, the algorithm doesn't seem to make any changes to the String:
var x = prompt("Enter String");
for (var i=0; i<=x.length;i++) {
if (x[i] == " ") {
x[i] = "";
}
}
alert(x);
Iterate over the string copying characters, skipping spaces. Your code doesn't work because strings are immutable, so you cannot change characters within the string by doing x[i] = 'c'.
See Are JavaScript strings immutable? Do I need a "string builder" in JavaScript?
var string = 'Hello How are you';
var noSpaces = '';
for (var i = 0; i < string.length; i++) {
if (string.charAt(i) != ' ' ) {
noSpaces += string.charAt(i);
}
}
alert(noSpaces);
Your code is not working because, probably for strings, similar to a getter, there is no setter for indexed approach(x[0] = "w"). You cannot consider a string as an array. Its a special form of object (immutable object) that can be accessed with index, but strictly there is no setter in this approach.
You can fix your code by changing like below,
var x = prompt("Enter sum or 'e' to Exit");
var modified = "";
for (var i=0; i<x.length;i++) {
if (x[i] != " ") {
modified += x[i];
}
}
alert(modified);
And you can do this in other better ways like below by using regex,
var x = prompt("Enter sum or 'e' to Exit");
x = x.replace(/\s/g,"");
In your code you just compare the value and try to replace with same variable but it's not possible to replace same with variable, just stored your value with new variable some thing like below
var x = prompt("Enter sum or 'e' to Exit");
var v='';
for (var i=0; i<x.length;i++) {
if (x[i] != " ") {
v +=x[i];
}
}
alert(v);
Here is the link https://jsfiddle.net/rqL3cvog/
Another approach, which updates the variable x and does not use another variable is to use a reverse for loop and use slice to take the string before and after i:-
var x = prompt("Enter String");
for (var i = x.length; i--;) {
if (x[i] == " ") {
x = x.slice(0, i) + x.slice(i + 1, x.length);
}
}
alert(x);
Or, a reverse for loop with substr :-
var x = prompt("Enter String");
for (var i = x.length; i--;) {
if (x[i] == " ") {
x = x.substr(0, i) + x.substr(i + 1);
}
}
alert(x);
Hie ,
Please check below code. Its lengthy. But others can help to make it short. Check output
var x = prompt("Hello how are you");
y = ''
flag = false
for (var i=0; i<x.length;i++) {
if (x[i] == " ") {
flag= true
}
else {
if (flag == true) {
y += ' '
y += x[i]
flag = false
}
else {
y += x[i]
}
}
}
alert(y)
Output is : "Hello how are you"
Code just sets a flag when you get a space in x[i] & when you get next character its just add single space instead of whitespace & adds next character to output string & again sets flag to false.

how to increment the value of a char in Javascript

How do I increment a string "A" to get "B" in Javascript?
function incrementChar(c)
{
}
You could try
var yourChar = 'A'
var newChar = String.fromCharCode(yourChar.charCodeAt(0) + 1) // 'B'
So, in a function:
function incrementChar(c) {
return String.fromCharCode(c.charCodeAt(0) + 1)
}
Note that this goes in ASCII order, for example 'Z' -> '['. If you want Z to go back to A, try something slightly more complicated:
var alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('')
function incrementChar(c) {
var index = alphabet.indexOf(c)
if (index == -1) return -1 // or whatever error value you want
return alphabet[index + 1 % alphabet.length]
}
var incrementString = function(string, count){
var newString = [];
for(var i = 0; i < string.length; i++){
newString[i] = String.fromCharCode(string[i].charCodeAt() + count);
}
newString = newString.join('');
console.log(newString);
return newString;
}
this function also can help you if you have a loop to go through

Writing a program to find out the sum of the negative elements and positive elements of the array

My code runs well up until the point it is expected to return the result - it does not add up any of the values entered by the user.
a = (prompt("a:"));
b = (prompt("b:"));
c = (prompt("c:"));
negativeSum = Number(0);
positiveSum = Number(0);
var test = [a, b, c];
for (i = 0; i < test.length; i++) {
if (isNaN(test[i])) {
alert(test[i] + " : incorrect input.");
}
else
if (test[i] < 0) {
alert(test[i] + " : positive.")
negativeSum = Number(test[i]++);
}
else {
alert(test[i] + " : positive.")
positiveSum = Number(test[i]++);
}
}
alert(positiveSum + " : sum of +ve elements");
alert(negativeSum + " : sum of -ve elements");
isn't sum of negatives always less then sum of positives.
if you speaking about absolute diff.
than try
if (test[i] < 0) {
alert(test[i] + " : positive.")
negativeSum += Number(test[i]);
}
else {
alert(test[i] + " : positive.")
positiveSum += Number(test[i]);
}
//after the loop
return Math.abs(negativeSum) > positiveSum;
Several things - no need for Number(0) - just using 0 will do.
The line:
positiveSum = Number(test[i]++);
Simply assigns the value of test[i] + 1 (this is what the post increment ++ operator does) to positiveSum. It doesn't add it up to positiveSum (same is true for negativeSum.
This should work better:
negativeSum = 0;
positiveSum = 0;
var test = [a, b, c];
for (i = 0; i < test.length; i++) {
if (isNaN(test[i])) {
alert(test[i] + " : incorrect input.");
}
else
if (test[i] < 0) {
alert(test[i] + " : positive.")
negativeSum += test[i];
}
else {
alert(test[i] + " : positive.")
positiveSum += test[i];
}
}
In my code the line:
negativeSum += test[i];
Is equivalent to:
negativeSum = negativeSum + test[i];
You're not summing anything, you're incrementing each number you've input. You want positiveSum += (each number).
You should also convert the element to a number before doing the comparison to zero and the rest.

Javascript: getting rid of nested loop

It's been a while since I wrote any Javascript. Is there a more elegant way to do this. Specifically want to get rid of the second loop:
<script>
var number = 0;
for (var i=1; i<11; i++) {
for (var x=1; x<11; x++) {
if (i==1) {
number = x;
} else {
number = Math.pow(i, x);
}
document.write(number + " ");
if (x == 10) {
document.write("<br>");
}
}
}
</script>
I would stick with 2 loops but i would change one if statement and move it after the 2nd loop and avoid document.write and insert it all at once to reduce the number of time you change the DOM
let result = ''
for (let i = 1; i < 11; i++) {
for (let x = 1; x < 11; x++)
result += (i==1 ? x : Math.pow(i, x)) + ' '
result += '<br>'
}
document.body.insertAdjacentHTML('beforeend', result)
Edit If you really don't want the 2nd loop:
let result = ''
// you must swap the condition to check for x instead of i
for (let i = 1, x = 1; x < 11; i++) {
result += (x==1 ? i : Math.pow(x, i)) + ' '
// and reset i and increase x yourself
if (i == 10) {
i = 0
x++
result += '<br>'
}
}
document.body.insertAdjacentHTML('beforeend', result)
Edit2 just for the fun: No for loops.
Just a recursive function :P
function build(i = 1, x = 1, res = '') {
res += (x == 1 ? i : Math.pow(x, i)) + ' '
i == 10 ? (x++, i=1, res += '<br>') : i++
return x == 11 ? res : build(i, x, res)
}
document.body.insertAdjacentHTML('beforeend', build())
In terms of 'elegancy', I'd go for for... in loops or map function. That doesn't solve your nested loop though.
On a side note, nested loops are not necessarily bad. If that's the correct way to implement the specific algorithm, then that's how it is.
Using Math.pow() is un-necessary overhead. Nested loops are not necessarily bad.
var number = 0;
for (var i=1; i<11; i++) {
document.write(i + " ");
number = i;
for (var x=2; x<11; x++) {
number = (i == 1) ? x : number * i;
document.write(number + " ");
}
document.write("<br>");
}
Another way of doing it with 1 loop only, tho not as clean:
var number = 0;
var x = 1;
var calc = 0;
var calcx = 1;
var increment = false;
for (var i=1; i<101; i++) {
increment = false;
calc = i % 10;
if(calc == 0){
calc = 10;
increment = true;
}
if (calcx==1) {
number = calc;
} else {
number = Math.pow(calcx, calc);
console.log(calcx+" "+calc);
}
document.write(number + " ");
if (i % 10 == 0) {
document.write("<br>");
}
if(increment){
calcx++;
}
}
Here's another way with only one loop:
[...Array(100)].map((_,i) => {
document.write(((i>9)?Math.pow(Math.floor((i+10)/10),(i%10)+1):i+1) + ' ' + ((i%10==9)?'<br>':''));
});

Categories

Resources