it("should know properties that are functions act like methods", function() {
var meglomaniac = {
mastermind : "Brain",
henchman: "Pinky",
battleCry: function(noOfBrains) {
return "They are " + this.henchman + " and the" +
Array(noOfBrains + 1).join(" " + this.mastermind);
}
};
var battleCry = meglomaniac.battleCry(4);
expect('They are Pinky and the Brain Brain Brain Brain').toMatch(battleCry);
});
What is the definition of Array in this code (line 7)? I looked it up and it looks like it's an Array.of() command which generates an empty array of length n which in this case would be 5? So why does it end up with only 4 brain inputs assuming that is the correct assumption? Or is this array() doing something else?
battleCry(4) means that Array(noOfBrains + 1) will indeed have a length of 5:
[empty, empty empty, empty, empty]
But when you .join those 5 elements, you only insert something into the spaces between them, and there are only 4 spaces:
[empty, empty empty, empty, empty]
// ^ ^ ^ ^
So, you end up with 4 occurrences of this.mastermind in the resulting string.
This code is quite confusing. I'd strongly prefer something like .repeat instead:
var meglomaniac = {
mastermind : " Brain",
henchman: "Pinky",
battleCry: function(noOfBrains) {
return `They are ${this.henchman} and the${this.mastermind.repeat(noOfBrains)}`
}
};
var battleCry = meglomaniac.battleCry(4);
console.log(battleCry === 'They are Pinky and the Brain Brain Brain Brain');
Array is just the array constructor. It's not really anything special, it just creates an array which has a length of the parameter (when passed a number).
You can avoid having to manually add 1 to the number of elements in the Array to overcome the problem, by using Array.fill().
Array(4).fill("Brain").join(" "); // have an array of 4 elements,
// fill each vacant spot with "Brain"
// and flatten it by separating elements
// by a space
//Brain Brain Brain Brain
So your code can be simplified as:
Array(noOfBrains).fill(this.mastermind).join(" ");
Related
So i ran the code about 50 times and each time it returned olg / 1 so What is wrong
alert("welcome to word unscrambler undscramble this")
console.log("i am not a distraction")
document.write("i am not a distraction either")
var r = ["pttoao","recme","logd","teey","olg"]
var g=Math.floor(Math.random() *+ 6);
if (g=="0") {select =("pttoao")}
else if(g=="1"){select=("recme")}
else if (g==2){select="logd"}
else if(g==3){select="dre"}
else if(g==4){select="olg"}
if(select=="pttoao"){realword="potato"}
if(select=="recme"){realword="creme"}
if(select=="logd"){realword="gold"}
if(select=="teey"){realword="yeet"}
if(select="olg"){realword="log"}
var awnser= prompt("unscramble "+select)
if(awnser==realword){alert("correct")
}else{
alert("incorrect")}
maybe it is that it cant randomly select words
Here's some code that works for any amount of words.
Notice the structure: array of objects, objects have the real word and the scramble of it.
The random is relative to the amount of words.
I've combined the prompt, the check, and the alert into one line.
"Simplify by complication..." :)
var words=[
{real:"potato", scrambled:"pttoao"},
{real:"creme", scrambled:"recme"},
{real:"gold", scrambled:"logd"},
{real:"yeet", scrambled:"teey"},
{real:"log", scrambled:"olg"}
];
var random=Math.floor(Math.random()*words.length);
alert(
prompt("Unscramble: "+words[random].scrambled)
==
words[random].real?
"Correct":
"Wrong"
);
var g=Math.floor(Math.random() *+ 6 )
should be replaced with following as array elements index starts from
zero and array "r" contains 5 elements
var g=Math.floor(Math.random() * 5);
if(select="olg"){realword="log"}
here, you have assigned "olg" value to select variable. Inside "if" condition assignment is simply returning assigned value which is "olg" that makes it true and executes realword="log"
It should be replaced with
if(select=="olg"){realword="log"}
Hello I'm trying to understand recursion in JavaScript.
So far I have:
function countVowels(string) {
let vowelCount = 0;
// if we're not at the end of the string,
// and if the character in the string is a vowel
if (string.length - 1 >= 0 && charAt(string.length -1) === "aeiouAEIOU") {
//increase vowel count every time we iterate
countVowels(vowelCount++);
}
return vowelCount;
}
First of all, this is giving me issues because charAt is not defined. How else can I say "the character at the current index" while iterating?
I can't use a for-loop - I have to use recursion.
Second of all, am I using recursion correctly here?
countVowels(vowelCount++);
I'm trying to increase the vowel count every time the function is called.
Thanks for your guidance.
If you're interested, here is a version that does not keep track of the index or count, which might illuminate more about how the recursion can be done.
function countVowels(string) {
if (!string.length) return 0;
return (
"aeiou".includes(string.charAt(0).toLowerCase()) +
countVowels(string.substr(1))
);
}
console.log(countVowels("")); // 0
console.log(countVowels("abcde")); // 2
console.log(countVowels("eee")); // 3
// Note that:
console.log('"hello".substr(1)', "hello".substr(1)) // ello
console.log('"hello".charAt(0)', "hello".charAt(0)) // h
console.log('"aeiou".includes("a")', "aeiou".includes("a")) // true
console.log('"a".includes("aeiou")', "a".includes("aeiou")) // false
Our base case is that the string is empty, so we return 0.
Otherwise, we check if the first character in the string is a vowel (true == 1 and false == 0 in javascript) and sum that with counting the next (smaller by one) string.
You are making two mistakes:
You should have three parameters string , count(count of vowels) and current index i.
You should use includes() instead of comparing character with "aeiouAEIOU"
function countVowels(string,count= 0,i=0) {
if(!string[i]) return count
if("aeiou".includes(string[i].toLowerCase())) count++;
return countVowels(string,count,i+1);
}
console.log(countVowels("abcde")) //2
As asked by OP in comments "Can you please explain why it'sif("aeiou".includes(string[i].toLowerCase())) instead of if(string[i].includes("aeiou".toLowerCase()))"
So first we should know what includes does. includes() checks for string if it includes a certain substring passed to it or not. The string on which the method will be used it will be larger string and the value passed to includes() be smaller one.
Wrong one.
"a".includes('aeiou') //checking if 'aeiou' is present in string "a" //false
Correct one.
"aeiou".includes('a') //checking if 'a' is present in string "aeiou" //true
One possible solution would be:
function countVowels(string, number) {
if (!string) return number;
return countVowels(string.slice(1), 'aeiouAEIOU'.includes(string[0])? number + 1 : number);
}
// tests
console.log('abc --> ' + countVowels('abc', 0));
console.log('noor --> ' + countVowels('noor', 0));
console.log('hi --> ' + countVowels('hi', 0));
console.log('xyz --> ' + countVowels('xyz', 0));
and you should call your function like: countVowels('abc', 0)
Notes about your solution:
you always reset vowelCount inside your function, this usually does not work with recursion.
you defined your function to accept a string, but recall it with an integer in countVowels(vowelCount++); this it will misbehave.
always remember that you have to define your base case first thing in your recursion function, to make sure that you will stop sometime and not generate an infinite loop.
Alternative ES6 solution using regex and slice() method. Regex test() method will return true for vowels and as stated in a previous answer JavaScript considers true + true === 2.
const countVowels = str => {
return !str.length ? 0 : /[aeiou]/i.test(str[0]) + countVowels(str.slice(1));
}
I want to grab the user input from an input tag including everything after the # symbol and up to a space if the space exists. For example:
If the user input is "hello#yourname"
I want to grab "yourname"
If the user input is "hello#yourname hisname"
I want to grab "yourname" because it is after the # symbol and ends at the space.
I have some code written that attempts to grab the user input based on these rules, but there is a bug present that I can't figure out how to fix. Right now if I type "hello#yourname hisname"
My code will return "yourname hisn"
I don't know why the space and four characters "hisn" are being returned. Please help me figure out where the bug is.
Here is my function which performs the user input extraction.
handleSearch(event) {
let rawName, nameToSearch;
rawName = event.target.value.toLowerCase();
if (rawName.indexOf('#') >= 0 && rawName.indexOf(' ') >= 0) {
nameToSearch = rawName.substr(rawName.indexOf('#') + 1, rawName.indexOf(' ') - 1);
} else if (rawName.indexOf('#') >= 0 && rawName.indexOf(' ') < 0) {
nameToSearch = rawName.substr(rawName.indexOf('#') + 1);
} else {
nameToSearch = '';
}
return nameToSearch;
}
Working example:
handleSearch(event) {
let rawName = event.target.value.toLowerCase();
if (rawName.indexOf("#") === -1) {
return '';
}
return (rawName.split("#")[1].split(" "))[0];
}
You have to handle a lack of "#", but you don't need to handle the case where there is a space or not after the "#". The split function will still behave correctly in either of those scenarios.
Edit: The specific reason why OP's code doesn't work is because the substr method's second argument is not the end index, but the number of characters to return after the start index. You can use the similar SUBSTRING method instead of SUBSTR to make this easier. Change the line after the first if statement as follows:
nameToSearch = rawName.substring(rawName.indexOf('#') + 1, rawName.indexOf(' '));
const testCases = [
"hello#yourname",
"hello#yourname hisname"
];
for (let test of testCases) {
let re = /#(.*?)(?:\s|$)/g;
let result = re.exec(test);
console.log(result[1]);
}
Use regex instead if you know how the string will be created.
You could do something like this--
var string = "me#somename yourname";
var parts = string.split("#");
var parts2 = parts[1];
var yourPart = parts2.split(" ");
console.log(yourPart[0]);
NOTE:
I am suggesting it just because you know your string structure.
Suggestion
For your Piece of code I think you have some white space after hisn that is why it is returning this output. Try to replace all the white spaces with some character see if you are getting any white space after hisn.
I'm not sure of the language your code is in (there are several it 'could be', probably Javascript), but in most languages (including Javascript) a substring function 'starts at' the position of the first parameter, and then 'ends at' that position plus the second parameter. So when your second parameter is 'the position of the first space - 1', you can substitute 'the position of the first space - 1' with the number 13. Thus, you're saying 'get a substring by starting one after the position of the first # character i.e. position 6 in a zero-based system. Then return me the next 13 characters.'
In other words, you seem to be trying to say 'give me the characters between position 6 and position 12 (inclusive)', but you're really saying 'give me the characters between position 6 and position 18 (inclusive)'.
This is
y o u r n a m e h i s n
1 2 3 4 5 6 7 8 9 10 11 12 13
(For some reason I can't get my spaces and newlines to get preserved in this answer; but if you count the letters in 'yourname hisn' it should make sense :) )
This is why you could use Neophyte's code so long as you can presume what the string would be. To expand on Neophyte's answer, here's the code I would use (in the true branch of the conditional - you could also probably rename the variables based on this logic, etc.):
nameToSearch = rawName.substr(rawName.indexOf('#') + 1;
var nameFromNameToSearch = nameToSearch.substr(nameToSearch.indexof(' ') - 1;
nameFromNameToSearch would contain the string you're looking for. I haven't completely tested this code, but I hope it 'conceptually' gives you the answer you're looking for. Also, 'conceptually', it should work whether there are more than one '#' sign, etc.
P.S. In that first 'rawName.substr' I'm not giving a second parameter, which in Javascript et al. effectively says 'start at the first position and give me every character up to the end of the string'.
This is all in the context of a larger program, so Im going to try keep it simple, showing the offending lines only. I have an array of values that are numbers in string form a la "84", "32", etc.
Yet THIS line
console.log(unsolved.length + " " + unsolved[0] + " " + parseInt(unsolved[0]) + " " + parseInt("84"));
prints:
4 "84" NaN 84
"84" is the array element Im trying to parseInt! Yet it won't work unless I take it out of the context of an array and have it explicitly written. What's going on?
You can try removing the quotations from the string to be processed using this function:
function stripAlphaChars(source) {
var out = source.replace(/[^0-9]/g, '');
return out;
}
Also you should explicitly specify that you want to parse a base 10 number:
parseInt(unsolved[0], 10);
parseInt would take everything from the start of its argument that looks like a number, and disregard the rest. In your case, the argument you're calling it with starts with ", so nothing looks like a number, and it tries to cast an empty string, which is really not a number.
You should make sure that the array element is indeed a string which is possible to parse to a number. Your array element doesn't contain the value '84', but actually the value '"84"' (a string containing a number encapsulated by ")
You'll want to remove the " from your array elements, possible like this:
function removeQuotationMarks(string) {
return (typeof string === 'string') ? string.replace(/"|'/g, '') : string;
}
unsolved = unsolved.map(removeQuotationMarks);
Now all the array elements should be ready to be parsed with parseInt(unsolved[x], 10)
First we need to replace " to ' in give data using Regex and replace and then we need to cast.
var i = 1;
var j = "22"
function stringToNumber(n) {
return (typeof n === 'string') ? parseInt(Number(n.replace(/"|'/g, ''))) : n;
}
console.log(stringToNumber(i)); // 1
console.log(stringToNumber(j)); // 22
Is there a way to resolve mathematical expressions in strings in javascript? For example, suppose I want to produce the string "Tom has 2 apples, Lucy has 3 apples. Together they have 5 apples" but I want to be able to substitute in the variables. I can do this with a string replacement:
string = "Tom has X apples, Lucy has Y apples. Together they have Z apples";
string2 = string.replace(/X/, '2').replace(/Y/, '3').replace(/Z/, '5');
However, it would be better if, instead of having a variable Z, I could use X+Y. Now, I could also do a string replace for X+Y and replace it with the correct value, but that would become messy when trying to deal with all the possible in-string calculations I might want to do. I suppose I'm looking for a way to achieve this:
string = "Something [X], something [Y]. Something [(X+Y^2)/(5*X)]";
And for the [___] parts to be understood as expressions to be resolved before substituting back into the string.
Thanks for your help.
There's no direct, built-in way (well, okay, perhaps there is — see below), but if you use the callback feature of the replace function, where the replacement can be a function rather than a string (the return value is what's substituted in), you can implement this fairly easily.
For instance, suppose you use the Ruby notation #{xyz} for your placeholders. This code loops through those:
var mappings, str;
str = "One #{X} three #{Y} five";
mappings = {
"X": 2,
"Y": 4
};
str = str.replace(/\#\{([^#]+)\}/g, function(match, key) {
var result;
result = mappings[key];
/* ...processing here */
return result;
});
The resulting string is One 2 three 4 five, because #{X} and #{Y} have been replaced via lookup. You can look at the key and see whether it's an expression and needs to be evaluated rather than simply looked up. That evaluation is where your real work comes in.
Now, you could use with and eval to achieve expression support; change the result = mapping[key]; line above to this:
with (mappings) {
result = eval(key);
}
If you feed the string "One #{X} three #{Y} five #{X + Y * 2}" into that, the result is One 2 three 4 five 10 — because 2 + 4 * 2 = 10.
That works because with sticks the given object on top of the scope chain, so it's the first thing checked when resolving an unqualified reference (like X), and eval executes Javascript code — and so can evaluate expressions — and magically does so within the scope in which it's called. But beware; as Eric pointed out, not all operators are the same in various forms of expression, and in particular Javascript interprets ^ to mean "bitwise XOR", not "to the power of". (It doesn't have an exponent operator; you have to use Math.pow.)
But you need to be very careful about that sort of thing, both with and eval (each in their own way) can be problematic. But the main issues with with are that it's hard to tell where something comes from or where it will go if you do an assignment, which you're not; and the main issues with eval come from using it to interpret strings you don't control. As long as you keep safeguards in place and are aware of the issues...
Boiling that down into a function:
function evaluate(str, mappings) {
return str.replace(/\#\{([^#]+)\}/g, function(match, key) {
var result;
with (mappings) {
result = eval(key);
}
return result;
});
}
alert(evaluate(
"The expression '(#{X} + #{Y}) * 2' equals '#{(X + Y) * 2}'",
{"X": 2, "Y": 4}
)); // alerts "The expression '(2 + 4) * 2' equals '12'"
alert(evaluate(
"The expression '(#{X} + #{Y}) * 2' equals '#{(X + Y) * 2}'",
{"X": 6, "Y": 3}
)); // alerts "The expression '(6 + 3) * 2' equals '18'"
The only way I can think of to achieve this would be a templating engine such as jTemplates. Also see the answers to this SO question.
Nice question:
function substitutestring(str,vals)
{
var regex = /\[[^\]]*\]/gi;
var matches = str.match(regex);
var processed = [];
for(var i = 0; i<matches.length; i++)
{
var match = matches[i];
processed[match] = match.slice(1,-1);
for(j in vals)
{
processed[match] = processed[match].replace(j,vals[j]);
}
processed[match] = eval("("+processed[match]+")");
}
for(var original in processed)
{
str = str.replace(original,processed[original]);
}
return str;
}
document.write(
substitutestring(
"[x] + [y] = [x+y]",
{"x": 1, "y": 2}
)
);
In ES6 you can now use template strings:
var X = 2, Y = 3;
string = Tom has ${X} apples, Lucy has ${Y} apples. Together they have ${X+Y} apples;