My code is below. I'm using isNaN() but the problem is it's still valid
function numberSearch(str) {
let sum = 0
let strCount = 0
if (str === "") {
return 0
};
for (let i = 0; i < str.length; i++) {
if (isNaN(Number(str[i]))) {
strCount = strCount + 1 // if it's true, +1
}
sum = sum + Number(str[i]) // if it's a number
}
return Math.round(sum / strCount);
}
//debugger;
let output = numberSearch('Hello6 ');
console.log(output); // --> 1
output = numberSearch('Hello6 9World 2,');
console.log(output); // --> 1
How can I count the number and calculate it?
When I using debugger sum is NaN .. I cant understand well.
The issue is that sum = sum + Number(str[i]) is being executed even if isNaN(Number(str[i])) === true because it is outside of the if block. You need to wrap it inside of the else block so that it only executes if the previous condition is false.
function numberSearch(str) {
let sum = 0
let strCount = 0
if (str === "") {
return 0
};
for (let i = 0; i < str.length; i++) {
if (isNaN(Number(str[i]))) {
strCount = strCount + 1 // if it's true, +1
} else {
sum = sum + Number(str[i]) // if it's a number
}
}
return Math.round(sum / strCount);
}
//debugger;
let output = numberSearch('Hello6 ');
console.log(output); // --> 1
output = numberSearch('Hello6 9World 2,');
console.log(output); // --> 1
The other way of doing this is with a continue statement. Think of continue the same way you think about an early return in a function, except for a loop.
For example, you've written:
function numberSearch(str) {
// . . .
if (str === "")
return 0
// . . .
}
This is called an "early return" or "early exit." The same technique can be used in a loop:
for (let i = 0; i <= 10; i++) {
if (i % 3 === 0) // matches every multiple of 3 (3, 6, 9, etc.)
continue;
console.log(i)
}
Here is your code again, this time using continue.
function numberSearch(str) {
let sum = 0
let strCount = 0
if (str === "") {
return 0
};
for (let i = 0; i < str.length; i++) {
if (isNaN(Number(str[i]))) {
strCount = strCount + 1 // if it's true, +1
continue
}
sum = sum + Number(str[i]) // if it's a number
}
return Math.round(sum / strCount);
}
//debugger;
let output = numberSearch('Hello6 ');
console.log(output); // --> 1
output = numberSearch('Hello6 9World 2,');
console.log(output); // --> 1
I recommend you go with the if-else version because for a loop as simple as this, the use of continue adds a little unnecessary metal-overhead.
That being said, if the logic within the loop grows (the part in the else statement), you may find it is easy to read if you do use the continue method. In the end, what really matters is what you personally feel is easier to read.
I would probably do it slightly different than in the original code, and find out how many numbers there are, and work from there
function numberSearch(str) {
if (!str) {
// early exit for null or ''
return 0;
}
// get all the chars, filter the non-numbers
const numbers = str.split('').filter( v => !isNaN(Number(v)));
// map all the numbers to numbers and sum them up
const sum = numbers.map( Number ).reduce( (agg, item) => agg + item, 0 );
// divide the sum by the length of the string - the amount of numbers found
// but always by at least 1 (so not to get a divide by 0 error when only all numbers are given)
return Math.round( sum / Math.max(1, str.length - numbers.length) );
}
let output = numberSearch('Hello6 ');
console.log(output); // --> 1
output = numberSearch('Hello6 9World 2,');
console.log(output); // --> 2
output = numberSearch('111111111');
console.log(output); // --> 9
output = numberSearch('');
console.log(output);
For the original code however, you should just add a continue in your if branch and your code will work (as long as not all characters are numbers, cause then you would divide by 0 and you didn't specify how to handle such a case)
for (let i = 0; i < str.length; i++) {
if (isNaN(Number(str[i]))) {
strCount = strCount + 1; // if it's true, +1
continue;
}
sum = sum + Number(str[i]); // if it's a number
}
Just remember to verify to not divde by 0 if all are numbers :)
Your main issue is that you add a number anyway. In the line sum = sum + Number(str[i]) is read for each and every character. So even the last char will be NaN and it would be added to the sum, making it NaN.
I'm not quite sure what you're trying to do here, it seems like you are trying to get the sum and divide it by the number of non number characters.
You need to skip those in the sum. There are plenty of ways to do it, and some other problems with the code, but to keep the changes to your code to a minimum I say, just do this:
function numberSearch(str) {
let sum = 0;
let strCount = 0;
if (str === "") {
return 0;
};
for (let i = 0; i < str.length; i++) {
if (isNaN(Number(str[i]))) {
strCount = strCount + 1; // if it's true, +1
} else {
sum = sum + Number(str[i]); // if it's a number
}
}
return Math.round(sum / strCount);
}
Think of the following case
for(let i = 0 ; i<str.length ; i++){
//str[0] is 'H', so fall into the first if-case
if(isNaN(Number(str[i]))){
strCount = strCount + 1 // if it's true, +1
}
//the code keep running but 'H' shouldn't fall into the following case
sum = sum + Number(str[i]) // if it's a number
}
return Math.round(sum/strCount);
I suggest you add one more if-else for each case which clearly state out each of the case. This makes it easier to recall memory when you come across the code days or months later.
for(let i = 0 ; i<str.length ; i++){
if(isNaN(Number(str[i]))){
strCount = strCount + 1
}else if(typeof str[i] === 'number'){
sum = sum + Number(str[i])
}
}
return Math.round(sum/strCount);
Related
function sumDigits(num) {
newStr = num.toString();
var sum = 0;
for(var i=0; i < newStr.length; i++) {
sum = sum + parseInt(newStr[i]);
}
return sum;
}
var output = sumDigits(1148);
console.log(output); // --> 14
Hey guys, my output is 14. However, my for loop falls apart if num is a negative number. Anyone got any ideas how to get past this? Presently, a negative number returns 'NaN'
I would suggest using a modulus approach here, which avoids the unnecessary cast from integer to string and vice-versa:
function sumDigits(num) {
var sum = 0;
while (num != 0) {
sum += num % 10;
num = num > 0 ? Math.floor(num / 10) : Math.ceil(num / 10);
}
return sum;
}
var output = sumDigits(1148);
console.log("1148 => " + output);
var output = sumDigits(-1148);
console.log("-1148 => " + output);
output = sumDigits(0);
console.log("0 => " + output);
Multiply the result?
function sumDigits(input) {
return Math.abs(input)
.toString()
.split("")
.reduce((sum, num) => sum + Number(num), 0)
* (input < 0 ? -1 : 1);
}
One of the examples.
function sumDigits(num) {
newStr = Math.abs(num).toString();
var sum = 0;
for(var i=0; i < newStr.length; i++) {
sum = sum + parseInt(newStr[i]);
}
return num >= 0 ? sum : -sum ;
}
var output = sumDigits(1148);
console.log(output); // --> 14
var output = sumDigits(-1148);
console.log(output); // --> -14
var output = sumDigits(0);
console.log(output); // --> 0
When you pass a negative number into your sumDigits() function and convert it to a string, the first character becomes the sign (-). So, you should get the absolute value to get rid of the sign. However, if you're expecting a negative value, then you should define a flag that indicates whether the parameter was a negative integer before it got converted, or simply multiply it again by the initial sign. So, you should modify your function like this:
function sumDigits(num) {
const seq = Math.abs(num).toString();
let sum = 0;
for (let i = 0; i < seq.length; i++) {
sum += parseInt(seq[i]);
}
return sum * Math.sign(num);
}
This question already has answers here:
How do you test for NaN in JavaScript?
(3 answers)
Closed 2 years ago.
my code is like that..
i m using isNaN() but problem is still valid
function numberSearch (str) {
let sum = 0;
let strCount = 0;
if(str === "") {
return 0;
};
for(let i = 0 ; i < str.length; i++) {
if (isNaN(Number(str[i]))) {
strCount = strCount + 1 // if it's true, +1
}
sum = sum + Number(str[i])
}
return Math.round(sum/strCount);
}
let output = numberSearch('Hello6 ');
console.log(output); // --> 1
output = numberSearch('Hello6 9World 2,');
console.log(output); // --> 1
How can I count the number and calculate it?
I'm using isNaN(), but when i using debugger sum is 'NaN'
I cant treat well.. i cant understand well..
Scroll for answer to edited question.
NaN === NaN
will be false, there is a good explanation given here.
Try using isNaN() for your check instead of comparison.
Edit: As far I understood you, you want to get a rounded average of the numbers found within the string. The if check is modified accordingly -- it has to increase count and sum, if there is a number being checked:
function numberSearch (str) {
let sum = 0;
let count = 0;
if (str === '') {
return 0;
};
for (let i = 0 ; i < str.length ; i++) {
// if character is not empty and is a number,
// increase count and sum
if (str[i] !== ' ' && !isNaN(Number(str[i]))) {
count++;
sum = sum + Number(str[i]);
}
}
return Math.round(sum/count);
}
let output = numberSearch('Hello6 ');
console.log(output); // 6 now, 6 / 1
output = numberSearch('Hello6 9World 2,');
console.log(output); // --> 6 now, 17 / 3
Question:
Write a function called sumDigits.
Given a number, sumDigits returns the sum of all its digits.
var output = sumDigits(1148);
console.log(output); // --> 14
If the number is negative, the first digit should count as negative.
var output = sumDigits(-316);
console.log(output); // --> 4
This is what I currently have coded and it works for positive values but I can't wrap my head around how to tackle the problem when given a negative value. When -316 is put into the function, NaN is returned and I understand that when I toString().split('') the number, this is what is returned: ['-', '3', '1', '6']. How do I deal with combining index 0 and 1?
function sumDigits(num) {
var total = 0;
var newString = num.toString().split('');
for (var i = 0; i < newString.length; i ++) {
var converted = parseInt(newString[i]);
total += converted;
}
return total;
}
sumDigits(1148);
Any hints on what methods I should be using? and is there a smarter way to even look at this?
This should do it:
function sumDigits(num) {
var total = 0;
var newString = num.toString().split('');
for (var i = 0; i < newString.length; i ++) {
if(newString[i]==='-') { //check to see if the first char is -
i++; //if it is, lets move to the negative number
var converted = parseInt(newString[i]); // parse negative number
total -= converted; // subtract value from total
continue; // move to the next item in the loop
}
var converted = parseInt(newString[i]);
total += converted;
}
return total;
}
console.log(sumDigits(-316));
You could always use String#replace with a function as a parameter:
function sumDigits (n) {
var total = 0
n.toFixed().replace(/-?\d/g, function (d) {
total += +d
})
return total
}
console.log(sumDigits(-1148)) //=> 14
One way to do this, is to do a split that will keep the minus and the first digit together, not split.
You can do that with a regular expression, and use match instead of split:
var newString = num.toString().match(/-?\d/g);
function sumDigits(num) {
var total = 0;
var newString = num.toString().match(/-?\d/g);
for (var i = 0; i < newString.length; i++) {
var converted = parseInt(newString[i]);
total += converted;
}
return total;
}
var result = sumDigits(-316);
console.log(result);
In a bit shorter version, you could use map and reduce, like this:
function sumDigits(num) {
return String(num).match(/-?\d/g).map(Number).reduce( (a, b) => a+b );
}
console.log(sumDigits(-316));
Is there a smarter way to even look at this?
You can avoid the conversion from number to string and back by using the modulo operator to extract the last digit. Repeat this step until you got all digits:
function sumDigits(num) {
let total = 0, digit = 0;
while (num != 0) {
total += digit = num % 10;
num = (num - digit) * 0.1;
}
return total < 0 ? digit + digit - total : total;
}
console.log(sumDigits(-316)); // 4
console.log(sumDigits(1148)); // 14
console.log(sumDigits(Number.MAX_SAFE_INTEGER)); // 76
function sumDigits(num) {
let string = num.toString();
let zero = 0;
let total = 0;
for (var i = 0; i < string.length; i++) {
if (Math.sign(num) === 1) {
total = zero += Number(string[i]);
} else {
for (var i = 2; i < string.length; i++) {
total = (zero += Number(string[i])) - Number(string[1]);
}
}
}
return total;
}
Yet Another (Project Euler) Fibonacci Question: Using (vanilla) javascript, I'm trying to sum the even numbers <= a given limit:
First, something is wrong with my 'if' statement, as some of the results (below) are wrong:
function fibonacciSum(limit) {
var limit = limit;
var series = [1,2];
var sum = 0;
var counter = 0;
for (var i=1; i<=33; i++) { // 33 is arbitrary, because I know this is more than enough
var prev1 = series[series.length-1];
var prev2 = series[series.length-2];
var newVal = prev1+prev2;
series.push(newVal);
counter ++;
console.log("series "+ counter + " is: " + series);
if (series[i] % 2 === 0 && series[i] <= limit) { // intending to sum only even values less than/equal to arbitrary limit
// sum = sum + series[i];
sum += series[i];
}
/*
var sum = series.reduce(function(a,b) {
/*
possible to filter here for even numbers? something like:
if (a %2 === 0)
*/
return a+b;
});
*/
console.log("SUM " + counter + ": " + sum);
} // for loop
} // fibonacci
fibonacciSum(4000000);
Results:
series 1 is: 1,2,3
SUM 1: 2
series 2 is: 1,2,3,5
SUM 2: 2
series 3 is: 1,2,3,5,8
SUM 3: 2 // looking for a '10' here
series 4 is: 1,2,3,5,8,13
SUM 4: 10
series 5 is: 1,2,3,5,8,13,21
SUM 5: 10
series 6 is: 1,2,3,5,8,13,21,34
SUM 6: 10 // looking for '44' here
Can someone please explain why neither of these working as intended?
if (series[i] % 2 === 0) { ...
... or
if (series[i] % 2 === 0 && series[i] <= limit) { ...
And secondly, as you can see I had also tried to use series.reduce(... but I can't figure how to sum only the even values; is that doable/cleaner?
Thank you,
Whiskey T.
No need for arrays. Use three variables for let's say previous, current and next numbers in fibonacci sequence.
We can also begin the sequence with 2 an 3 because there are no other even numbers that will affect the result.
We initialize the sum of even numbers with 2 because it's the current number and it's even. In a do...while we advance with the numbers in sequence and if the new numbers are even we add them to the sum. Stop when limit is reached.
function fibEvenSum(limit) {
var prev = 1,
current = 2,
next;
var sum = 2;
do {
next = prev + current;
prev = current;
current = next;
if (current >= limit)
break;
if (current % 2 == 0)
sum += current;
} while (true)
return sum;
}
This algorithm can be improved using properties of odd and even numbers:
odd + odd = even
even + even = even
even + odd = odd
This should work for you...
var fibonacciSum = function(limit) {
var nMinus2 = 1, nMinus1 = 2, evensFound = [2], sum = nMinus1;
while (sum <= limit){
var n = nMinus1 + nMinus2;
if (n % 2 == 0){
sum += n;
if (sum > limit){
break;
}
evensFound.push(n);
}
nMinus2 = nMinus1;
nMinus1 = n;
}
console.log("Evens found - " + evensFound);
return evensFound;
};
var evensFound1 = fibonacciSum(4),
evensFound2 = fibonacciSum(10),
evensFound3 = fibonacciSum(60),
evensFound4 = fibonacciSum(1000);
$(evenResults).append(evensFound1
+ "<br/>" + evensFound2
+ "<br/>" + evensFound3
+ "<br/>" + evensFound4);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="evenResults"></div>
A solution in the spirit of the one your attempted — with arrays — though as pointed out, they are not necessary.
var i = 0, sequence = [1, 2], total = 0;
while (sequence.slice(-1)[0] < 4000000) {
sequence.push(sequence.slice(-1)[0] + sequence.slice(-2)[0]);
}
for ( i; i <= sequence.length; i++ ) {
if ( sequence[i] % 2 === 0 ) {
total += sequence[i];
}
}
I am trying to write a single javascript function that will take in a list of numbers as arguments and will output the number of odd number, number of negative numbers, will average the numbers, and will output the median. I believe I basically have completed all of the code, but am either confusing my syntax or am incorrectly returning.
Code:
var arrayAnalyze = function(numbers){
var oddNum = []; //Array of odd numbers
var negNum = []; //Array of negative numbers
var numSum = 0; // Sum of all numbers
var avgNum = 0; //Average of all numbers
var midNum = []; //Median number
//Return odd numbers to oddNum array
for (i = 0; i < numbers.length; i++){
if (numbers[i] % 2 !== 0){
oddNum.push(numbers[i]);
}
}
//Return negative numbers to negNum array
for (i = 0; i < numbers.length; i++){
if (Math.abs(numbers[i]) + numbers[i] === 0){
negNum.push(numbers[i]);
}
}
//Return sum of all numbers to numSum variable
for (i = 0; i < numbers.length; i++){
numSum += i;
}
//Return average of numbers to avgNum variable
avgNum = numSum / numbers.length;
//Return median of numbers to midNum array
numbers.sort(function(a,b){return a - b;});
var evenSplit = Math.floor(numbers.length / 2);
if(numbers.length % 2){
midNum = numbers[evenSplit];
}else{
midNum = (numbers[evenSplit - 1] + numbers[evenSplit]) / 2.0; }
midNum.push();
return "Odds: " + oddNum.length, "Negatives: " + negNum.length, "Average: " + avgNum.toFixed(2), "Median: " + midNum[0];
};
console.log(arrayAnalyze(7, -3, 0, 12, 44, -5, 3));
Output:
TypeError: numbers.sort is not a function
There's a number of errors that you'd want to correct - comments inline
var arrayAnalyze = function (numbers) {
var oddNum = []; //Array of odd numbers
var negNum = []; //Array of negative numbers
var numSum = 0; // Sum of all numbers
var avgNum = 0; //Average of all numbers
var midNum = []; //Median number
//Return odd numbers to oddNum array
for (i = 0; i < numbers.length; i++) {
// always check the element at index, i is just the index
if (numbers[i] % 2 !== 0) {
// return exits the currently running function! (not the block)
oddNum.push(numbers[i]);
}
}
//Return negative numbers to negNum array
for (i = 0; i < numbers.length; i++) {
// exclude 0 here
if (Math.abs(numbers[i]) + numbers[i] === 0 && numbers[i]) {
negNum.push(numbers[i]);
}
}
//Return sum of all numbers to numSum variable
for (i = 0; i < numbers.length; i++) {
numSum += numbers[i];
}
//Return average of numbers to avgNum variable
avgNum = numSum / numbers.length;
//Return median of numbers to midNum array
// if you are using a function you need to invoke it to get it's value
midNum.push((function median(numbers) {
// note that this will actually sort the elements of the array you pass in in-place
numbers.sort(function (a, b) { return a - b; });
var evenSplit = Math.floor(numbers.length / 2);
if (numbers.length % 2) {
return numbers[evenSplit];
} else {
return (numbers[evenSplit - 1] + numbers[evenSplit]) / 2.0;
}
})(numbers));
// use + to concatenate the strings, otherwise it just becomes a bunch of comma separated expressions
return "Odds: " + oddNum.length + ",Negatives: " + negNum.length + ",Average: " + avgNum.toFixed(2) + ",Median: " + midNum[0];
};
// an array is passed in using square brackets
console.log(arrayAnalyze([7, -3, 0, 12, 44, -5, 3]));
when a function hits a return statement it will exit out meaning the any code beneath the return will not get executed.
In your odd number sorter you use the %/Modulus on the counter/index rather than numbers[i] to use it on each element of the numbers array parameter. This also needs fixed when you push to the appropriate results array. I have spotted this same concept being done multiple times throughout the function so I would go back and correct that as it would break a couple things.
Also to give you a tip in the right direction in terms of learning return like other users are saying, let's take a look at this part of your code:
for (i = 0; i < numbers.length; i++){
return numSum += i;
}
You do not need to return numSum as your are returning its value later at the end. Just updated the variable you initialized at the beginning by doing the following (also updated in regards to my suggestion above):
for (i = 0; i < numbers.length; i++){
numSum += numbers[i];
}
You cleary are pretty confused about how the return keyword works; I suggest you to check out some documentation here and here.
As an example, you need to change that piece of code
if (numbers % 2 !== 0){
return oddNum.push(numbers);
}else{
return false;
}
into
if (numbers % 2 !== 0){
oddNum.push(numbers);
}
All the others if structures have the same error.
I believe you have a fundamental misunderstand of what return does. MDN has a page on it: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return#Examples
return interrupts code execution, exits the innermost function and returns a value to the caller.
function myFunction() {
return "foo";
alert("This will never be reached!");
}
alert(myFunction()) // Equivalent to alert("foo").
For example, in your code:
//Return odd numbers to oddNum array
for (i = 0; i < numbers.length; i++){
if (i % 2 !== 0){
return oddNum.push(i); // <- code execution will stop here
}else{
return false; // <- or here, whichever is reached first.
}
}
Which means your loop will never execute for more than one iteration. So when you call
console.log(arrayAnalyze(7, -3, 0, 12, 44, -5, 3));
The first value is odd, so the function will stop at return oddNum.push(i);. And since oddNum.push(i) itself returns nothing (undefined), arrayAnalyze will return undefined too, and the log will be equivalent to
console.log(undefined);
Which is what you are seeing.
In this case the returns are completely unnecessary and the loop should read:
//Return odd numbers to oddNum array
for (i = 0; i < numbers.length; i++){
if (i % 2 !== 0){
oddNum.push(i); // <- now code execution is not interrupted!
}
}
And so on, through the rest of the code.
Also, at the end you declare a function called median:
//Return median of numbers to midNum array
function median(numbers) {
[...]
}
But you never invoke it (calling median(someValue)), which means the code inside it will never be executed either. I haven't checked the code for mathematical correctness, but I believe you should just remove the median declaration and leave its body inside the main arrayAnalyze function.
Your code should look like this :
var arrayAnalyze = function (numbers) {
var oddNum = []; //Array of odd numbers
var negNum = []; //Array of negative numbers
var numSum = 0; // Sum of all numbers
var avgNum = 0; //Average of all numbers
var midNum = []; //Median number
//Return odd numbers to oddNum array
for (i = 0; i < numbers.length; i++) {
if (i % 2 !== 0) {
oddNum.push(numbers[i]);
}
}
//Return negative numbers to negNum array
for (i = 0; i < numbers.length; i++) {
if (Math.abs(numbers[i]) + numbers[i] === 0) {
negNum.push(numbers[i]);
}
}
//Return sum of all numbers to numSum variable
for (numbers[i] = 0; numbers[i] < numbers.length; numbers[i]++) {
numSum += numbers[i];
}
//Return average of numbers to avgNum variable
avgNum = numSum / numbers.length;
//Return median of numbers to midNum array
var newArrayOfNumber = numbers;
newArrayOfNumber.sort();
var evenSplit = Math.floor(newArrayOfNumber.length / 2);
if (newArrayOfNumber.length % 2) {
midNum = newArrayOfNumber[evenSplit];
} else {
midNum = (newArrayOfNumber[evenSplit - 1] + newArrayOfNumber[evenSplit]) / 2.0;
}
return "Odds: " + oddNum.length + ", Negatives: " + negNum.length +", Average: " + avgNum.toFixed(2) +", Median: " + midNum;
};
When you call the function you should pass a array to it, so just add [] to your numbers like this : arrayAnalyze([7, -3, 0, 12, 44, -5, 3])
it should return :"Odds: 3, Negatives: 3, Average: 3.50, Median: 7.5"
When you want to add some number to a array in a for block or a if block, dont use return, just do the operation and if you want to break the for loop, use the line :
Break;
and when you want to access the number in your for loop, you should call the array and not only the i, like this : number[i]
espering that it help you
sorry for my mistakes in writting in english