javascript global variable undefined when calling inside the new, additional function - javascript

Coding linting with JS to iterate through a text.
I have a few iterations that count a specific conditions, for example
sentences
are set to be added upon when there is '.' or '!'.
However, when I created a function that would print one string with information about number of sentences, overused words and so on, it shows up as undefined... Here's a piece of code
console.log(betterWords.length);
let counter = 0;
for (let i = 0; i < betterWords.length; i++){
if (betterWords[i] === 'really' || betterWords[i] === 'very' || betterWords[i] === 'basically'){
counter++
}
}
console.log('You used overused words ' + counter + ' times.');
let sentences = 0;
betterWords.forEach (word => {
if (word[word.length-1] === '.' || word[word.length-1] === '!'){
sentences++
}
});
console.log('There are ' + sentences + ' sentences');
numberOfWords = betterWords.length;
const printFunction = (betterWords, counter, sentences) => {
return('The number of words in text is ' + numberOfWords + ' There are ' + sentences + ' and overused words are used ' + counter + ' times.');
};
console.log(printFunction());
Output
182
You used overused words 8 times.
There are 12 sentences
The number of words in text is 182 There are undefined and overused words are used undefined times. I am mentioning sentences as one example here. One can see that numberOfWords give a proper output
As one can see once sentences return 12, the other time it's undefined.

Related

Making the full sentence bold, even after added 'and' in javascript

I have a question regarding the message I'd like to display based on some values.
I have 4 categories that have some values and I need to display the message if they show high risk. The message is based on the number of risks which can be from 1 to 4 factors hence two messages where I'm using "factor IS" and "factors ARE".
My problem is I cannot make those factors bold after I add 'and' in my else statement. The beginning of the sentence is bold but not the last risk which comes after 'and'.
I'm adding 'and' before the last item of my array as I don't want comma (I found the code on: Array to Comma separated string and for last tag use the 'and' instead of comma in jquery).
Thanks for your help and suggestions!
function displayMessage() {
var getRiskFactors = calculateRisk();
var getRiskFactorsLength = getRiskFactors.length;
for (var i=0; i < getRiskFactorsLength; i++ ) {
if(getRiskFactorsLength === 1) {
var message = "Your main risk factor is your <b>" + getRiskFactors[0] + "</b>";
} else {
//this joins items from the array with comma if there's
//more than one factor.
//it also adds "AND" before the last item in the array
// instead of comma
var message = "Your main risk factors are your " + [getRiskFactors.slice(0, -1).join(", "), getRiskFactors.slice(-1)[0]].join(getRiskFactors.length < 2 ? "" : " and " + "</b>");
}
}
return message;
}
You are not starting and closing the bold tag
let getRiskFactors = [ 1,2,3,4 ];
var output = "Your main risk factors are your " + [ "<b>" + getRiskFactors.slice(0, -1).join(", "), getRiskFactors.slice(-1)[0]].join(getRiskFactors.length < 2 ? "" : "</b> and <b>") + "</b>";
document.body.innerHTML = output;
console.log(output);
You've misplaced your start <b> tag in the else clause and you are always adding a closing </b> tag after each and.
Just enclose the whole thing like this:
else {
var message = "Your main risk factors are your <b>" + [getRiskFactors.slice(0, -1).join(", "), getRiskFactors.slice(-1)[0]].join(getRiskFactors.length < 2 ? "" : " and ") + "</b>";
}
There is a balance between writing concise code and debuggable/readable code. This is a good illustration of trying to be too clever. I tried to make your code a little more readable.
In my experience I have found errors arise when using concatenation of strings and the ?: operator on the same line. Try the following code and edit as necessary.
var getRiskFactors = calculateRisk();
var getRiskFactorsLength = getRiskFactors.length;
for (var i=0; i < getRiskFactorsLength; i++ ) {
if(getRiskFactorsLength === 1) {
var message = "Your main risk factor is your <b>";
message+= getRiskFactors[0] + "</b>";
} else {
//this joins items from the array with comma if there's
//more than one factor.
//it also adds "AND" before the last item in the array
// instead of comma
var message = "Your main risk factors are your ";
var arraypart1 = getRiskFactors.slice(0, -1).join(", ");
var arraypart2 = getRiskFactors.slice(-1)[0];
var computation = getRiskFactors.length < 2 ? "" : " and ";
var joinedarray = [];
joinedarray.push(arraypart1);
joinedarray.push(arraypart2);
message += joinedarray.join(compution) + "</b>";
}
}
return message;

printing only even numbers between two numbers that are called in Javascript

function evenNumbers(minNumber, maxNumber){
var str = minNumber;
for (i=minNumber; i<=maxNumber; i++){
if (minNumber%2 ==0){
str += ',' + i;
}
}
return str;
}
console.log('evenNumbers(4,13) returns: ' + evenNumbers(4,13));
console.log('evenNumbers(3,10) returns: ' + evenNumbers(3,10));
console.log('evenNumbers(8,21) returns: ' + evenNumbers(8,21));
So, what I want the code to do is that in the given numbers in console.log,
for example, (4,13) it should print all the numbers that are EVEN between 4 and 13. However, instead of giving all the even numbers, the function gives me all the numbers that are between 4,13. How Could I fix the problem?
p.s is there any strcmp in javascript?
Wrong variable in if statement inside for loop.
if (minNumber%2 ==0){
str += ',' + i;
}
Should be
if (i%2 ==0){
str += ',' + i;
}
I presume you want to show the numbers between the min and max but not including either the min or max. In other words, evenNumbers(4,8) should just show 6. I also presume that both the min and max values will be integers.
I put all the logic in the for loop parameters, with the for loop body just placing those numbers and a comma into the output string. The final return value removes the last comma.
function evenNumbers(minNumber, maxNumber){
let str = '';
for (let i = Math.ceil((minNumber + 0.5) / 2) * 2; i < maxNumber; i += 2) {
str += `${i},`;
}
return str.slice(0,-1);
}
console.log('evenNumbers(4,13) returns: ' + evenNumbers(4,13));
console.log('evenNumbers(3,10) returns: ' + evenNumbers(3,10));
console.log('evenNumbers(8,21) returns: ' + evenNumbers(8,21));
console.log('evenNumbers(-8,5) returns: ' + evenNumbers(-8,5));
console.log('evenNumbers(-7,-2) returns: ' + evenNumbers(-7,-2));
console.log('evenNumbers(5,6) returns: ' + evenNumbers(5,6));
console.log('evenNumbers(10,2) returns: ' + evenNumbers(10,2));

Regex: How to return matches that are not in the bracket

So I technically already solved this issue, but I was hoping for a better solution using some funky regex.
The issue is:
We got strings this:
2+{2+(2)},
10+(20+2)+2
The goal is to match the 'plus' signs that are not in any sort of bracket.
i.e. in the previous strings it should match
2 + {2+(2)} ,
10 + (20+2) + 2
at the moment what I am doing is matching all plus signs, and then checking to see if the sign has any bracket in front of it (using regex), if it does then get rid of it.
I was hoping for a neater regex solution, is that possible?
To reiterate, I need the location of the strings, at the moment I am using javascript to do this, so ideally a js solution is preferred, but the pattern is really what I am looking for.
You could perhaps just replace everything inside () or {} with spaces:
'10 + (20+2) + 2'.replace(/\([^)]*?\)|\{[^}]*?\}/g, m => ' '.repeat(m.length));
This would result in
10 + + 2
Meaning the position of the strings aren't changed.
Note: It won't work well with nested things of the same type, ex (1 + (1 + 1) + 1), but it works with (1 + { 1 + 1 } + 1).
Bigger solution, using the same logic, but that works with nested stuff
var input = '10 + { 1 + (20 + (1 + { 3 + 3 } + 1) + 2) + 2 }';
var result = [];
var opens = 0;
for (var i = 0; i < input.length; ++i) {
var ch = input[i];
if (/\(|\{/.test(ch)) {
opens++;
result[i] = ' ';
}
else if (/\)|\}/.test(ch)) {
opens--;
result[i] = ' ';
}
else {
if (!opens) result[i] = input[i];
else result[i] = ' ';
}
}
result = result.join('');
// "10 + "

js last array item is undefined

I am trying to make a hangman game and in the beginning the game asks the user for the word. Once it has the word it fills the word letters one by one in an array using a for loop. Unfortunately the last array element is always undefined for some reason.
Code(JS):
for(i=0;i<word.length;i++)
{
if(i == word.length - 1)
{
wordLettersLeft = word.length;
$("#cEText").removeAttr("style");
$(".characterEnter").removeAttr("style");
$("#gBtn").text("Lopeta");
gameStarted = true;
pcArrayLength = pcArray.length;
lives = 4;
alert("Peli alkaa! Sinulla on " + lives + " yritystä jäljellä.");
alert("Vihje: " + hint);
alert("Sinulla on vielä " + wordLettersLeft + " arvattavaa kirjainta jäljellä.");
}
else
{
pcArray.push(word[i]);
}
}
This has a very simple reason: you are not adding the last letter to your pcArray. Let's assume our word is 'bird' (because bird is a word). Your code would go through the letters b, i and r and push those to your array, so far so good. But when it hits the d, it is at position word.length-1 - because the array length starts at 1 but the index starts at 0. Your if statement prevents it from pushing the last letter to the word. There are two solutions:
First, you could simply remove the else statement:
for(i=0;i<word.length;i++){
if(i == word.length - 1){
wordLettersLeft = word.length;
$("#cEText").removeAttr("style");
$(".characterEnter").removeAttr("style");
$("#gBtn").text("Lopeta");
gameStarted = true;
pcArrayLength = pcArray.length;
lives = 4;
alert("Peli alkaa! Sinulla on " + lives + " yritystä jäljellä.");
alert("Vihje: " + hint);
alert("Sinulla on vielä " + wordLettersLeft + " arvattavaa kirjainta jäljellä.");
}
pcArray.push(word[i]);
}
That will push every letter every time! However, There is a more efficient way:
for(i=0;i<word.length;i++)
pcArray.push(word[i]);
wordLettersLeft = word.length;
$("#cEText").removeAttr("style");
$(".characterEnter").removeAttr("style");
$("#gBtn").text("Lopeta");
gameStarted = true;
pcArrayLength = pcArray.length;
lives = 4;
alert("Peli alkaa! Sinulla on " + lives + " yritystä jäljellä.");
alert("Vihje: " + hint);
alert("Sinulla on vielä " + wordLettersLeft + " arvattavaa kirjainta jäljellä.");
This way you will only execute your initial code once instead of checking the if every time. You know your loop will only run for as long as there are letters, so why even bother with the if?
As #Shilly mentions in the comments, you can forego the for loop altogether by doing this:
pcArray = word.split('');
Let's say someone's inputing the word "Test". For i === 3 which is the last iteration, you enter the if clause and you're missing out on the else clause, which is where you're doing:
pcArray.push(word[i]);
What you want is to do this anyway, regardless of whether you're in the if or the else, so you can just drop the else clause and do it anyway.
The last step of your loop does not execute pcArray.push(word[i]);. So obvioulsy, the last value is missing.
But if you want to convert a string into an array, just do this :
var pcArray = word.split('');

How can I set a character limit of 100 without splitting words?

I want to cut a string every 100 characters without cutting up words.
var TmpArray=[];
var str = 'this string will be cut up after every 100 characters but it will cut into words';
str=str.replace(/[^a-z A-Z0-9]+/g, '');
str = str.replace(/\s{2,}/g, ' ');
var sp=(str.match(new RegExp(" ", "g")) || []).length;
var max=100;
//Spaces will be converted into %20 (later) so each space must count as 3 characters.
var FoundSpaces=sp*3;
var tmp=max-FoundSpaces;
var cut=str.match(new RegExp('.{1,'+tmp+'}', 'g'));
for (i = 0; i < cut.length; i++){
TmpArray.push(cut[i]);
}
console.log(TmpArray);
Output: ["this string will be cut up after every 100 characters b", "ut it will cut into words"]
So how can I prevent it from splitting words like it did?
Interesting question. I will propose one more implementation of how you can use just array methods, combination of split + reduce:
var str = 'This example of the string that we want to split by spaces only making sure that individual chunk is less or equal to specified number.';
// Split by spaces
str.split(/\s+/)
// Then join words so that each string section is less then 40
.reduce(function(prev, curr) {
if (prev.length && (prev[prev.length - 1] + ' ' + curr).length <= 40) {
prev[prev.length - 1] += ' ' + curr;
}
else {
prev.push(curr);
}
return prev;
}, [])
// Print for testting
.forEach(function(str) {
console.log(str + ' ' + str.length);
});
For this example I set maximum length of 40 characters.
Output:
This example of the string that we want 39
to split by spaces only making sure that 40
individual chunk is less or equal to 36
specified number. 17
One more demo: http://jsfiddle.net/9tgo6n1t/

Categories