Javascript - extract letters from an alphanumerical string via loop - javascript

Hello there StackOverflow people,
What I expected:
Removing the numbers of the string "23Ka5X". The loop counts the length and the if statement extracts the letters into an array letterMemory. When no letters are in the string, the message '"oh no numbers!" should be the output.
What I ran into:
I have been working on this for some time now but I can't find my mistake. I don't know if I missed a simple detail or made a big mess.
My feeling and console output:
var letterMemory = [];
function orderMsg(mixedMsg) {
for (var loopString = 0; loopString < mixedMsg.length; loopString++); {
if (isNaN(parseInt(mixedMsg.charAt[loopString]))); {
letterMemory.push(mixedMsg.charAt[loopString]);
return letterMemory;
} if (!isNaN(parseInt(mixedMsg.charAt[loopString]))) {
return "oh no numbers!";
}
}
}
console.log(orderMsg("23Ka5X"));
I feel like the issue is trying to push any letter into the array letterMemory via letterMemory.push(mixedMsg.charAt[loopString])
does not work how I imagine it.
I would be really grateful for your help!
I found a simple solution via .replace() but I really want to make it work with a loop and if statements since loops combined with if statements were my latest freecodecamp lessons and I want to get better at it.

The fixed code
function orderMsg(mixedMsg){
var letterMemory = []
for (var loopString = 0; loopString < mixedMsg.length; loopString++){
if (isNaN(mixedMsg[loopString])){
letterMemory.push(mixedMsg[loopString])
}
}
if (letterMemory.length){
return letterMemory
} else {
return 'oh no numbers!'
}
}
The issue was
The for loop was not executing since you terminated it with ; at the end.
charAt is a function, so you either do string.charAt(index), or you can also simply say string[index].
You are using the return statement within the for loop, so what will happen is even if the for loop ran (without the semi-colon at the end), it would run just once.
One other issue is that the variable letterMemory is declared outside the function so that means if you were to call this function twice, it would use the same letterMemory array.
-end of answer-
Additional read: you can use split, filter and ternary operator to condense the function as follows ..
function orderMsg(mixedMsg){
const letterMemory = mixedMsg.split('').filter(isNaN)
return letterMemory.length ? letterMemory : 'oh no numbers!'
}

This could be helpful,
function orderMsg(mixedMsg) {
for (var loopString = 0; loopString < mixedMsg.length; loopString++) {
if (isNaN(parseInt(mixedMsg.charAt(loopString)))) {
letterMemory.push(mixedMsg.charAt(loopString));
}
}
return letterMemory;
}
var arr = orderMsg("23s5");
if (arr.length == 0) {
console.log("oh no numbers!")
} else {
console.log(arr);
}

Use replace with regex globally, replacing all digits by an empty string:
string.replace(/[0-9]/g, "")

You have terminated for loop in the same line with ;.
charAt() is a method.
Return value after for loop ends.
var letterMemory = [];
function orderMsg(mixedMsg) {
for (var loopString = 0; loopString < mixedMsg.length; loopString++) {
var letter=parseInt(mixedMsg.charAt(loopString));
if(isNaN(letter)){
letterMemory.push(mixedMsg.charAt(loopString));
}
}
if(letterMemory.length>0){
return letterMemory;
}
else{
return "Oh no numbers!";
}
}
console.log(orderMsg("23Ka5X"));

Maybe try using .test to match the letters.
function orderMsg(str){
var result = [];
for(var letter of str){
if(/[a-zA-Z]+/g.test(letter)){
result.push(letter)
}
}
if(result.length === 0){
return 'Oh no numbers'
}
return result
}
For a more thorough explanation:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test

Related

recursion on returning vectors c++

Hey guys I am trying trying to right this javascript code into c++. I am doing quick sort and everything is straight forward minus the last step.
function quickSort(arr)
{
//base case if the arr is 1 or 0 then return the array
if(arr.length === 1 || arr.length === 0)
{
return arr;
}
var pivotIndex = Math.floor(arr.length/2);
var pivotValue = arr[pivotIndex];
var before = [];
var after = [];
for(var counter = 0; counter < arr.length; counter++)
{
if(counter === pivotIndex)
continue;
if(pivotValue <= arr[counter])
{
before.push(arr[counter])
}
else
{
after.push(arr[counter])
}
}
//this step I am having trouble rewriting in c++
return quickSort(after).concat(pivotValue).concat(quickSort(before));
}
I am having a hard time rewriting the recursive step in c++. I am not sure how concat 2 vector. I tried using the insert method but I keep getting an error about invalid use of void expression.
vector<int> quickSort(vector<int> arr)
{
if(arr.size() == 1 || arr.size() == 0)
{
return arr;
}
int pivotIndex = arr.size()/2;
int pivotValue = arr[pivotIndex];
vector<int> before;
vector<int> after;
//put values in before or after the piv
for(size_t counter = 0; counter < arr.size(); counter++)
{
if(counter == pivotIndex)
continue;
if(pivotValue <= arr[counter])
before.push_back( arr[counter]);
else
after.push_back( arr[counter]);
}
return //????? not sure how to do this
}
So, you realized that your core question was "how to concatenate two vectors", and you found a right answer: using insert. Now your question is about why you were getting "an error about invalid use of void expression." (That's the assumption my answer is for, at least.)
That's because you were likely trying to do something like the following:
return quickSort(after).insert( /* stuff */ );
which is wrong. In JavaScript, array.concat returns the concatenated array. It's return type is effectively Array, and so doing return arr.concat(arr2) returns an Array because arr.concat would return an Array. Further, in JavaScript, array.concat doesn't modify the array it was called on, but rather returns a new array.
In C++, however, vector.insert (#4 in the reference) returns void. That means it returns nothing. So when you try to return the result of insert, you get that error about invalid use of a void expression. Further, in C++, vector.insert does modify the vector it was called on.
So how do you use insert in this case?
vector<int> quickSort(vector<int> arr)
{
// ...
// Sort `before` and `after`
before = quickSort(before);
after = quickSort(after);
// Modify `after` and return it.
after.push_back(pivotValue);
after.insert(after.end(), before.begin(), before.end());
return after;
}
Note: My code isn't optimal and the idea of rewriting JS in C++ is also oddly specific. My answer is to simply outline the problem asked in the question, not to give a good C++ implementation of quick sort.
To concat two vector , you can use std::merge
like:std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(dst));

FreeCodeCamp: checking for palindromes

This is my first question, so I apologize if this isn't formatted correctly or placed in the proper area.
I just completed the FreeCodeCamp checking for palindromes challenge. I can't help but think my solution was very inelegant.
function palindrome(str) {
var cleanString = str.replace(/[^A-Za-z0-9]/g, '');
var lowerCleanString = cleanString.toLowerCase();
var lowerArr = lowerCleanString.split('');
var reverseArr = lowerArr.reverse();
var joinedArr = reverseArr.join('');
if (joinedArr === lowerCleanString) {
return true;
}
// Good luck!
else {
return false;
}
}
I know it worked, but is it possible to do some of these steps together or in a cleaner way?
Simple function to check for palindromes
function checkPalindrome(palindrome) {
return palindrome == palindrome.split('').reverse().join('');
}
function palindrome(str) {
var newstr = str.replace(/[\W_]/g,'').toLowerCase();
if(newstr === newstr.split('').reverse().join('')){
return true;
}
return false;
}
palindrome("five|\_/|four");
You can use many methods in one row like I've used them .It's more simple :)
Good luck
Wow, I really like the answers comparing the string to a string.split('').reverse().join('') version of itself. I didn't think about that. Forgot about the .reverse() function. I ended up processing the string and splitting it out into an array and then using a double counter for the loop to compare the first and last items in the array. Was kinda fun to learn how to do that, but I like the .reverse() function use better.
In case someone is curious about the for loop I used ...
for(let i = 0, j = arr.length-1; i < j; i++, j--) {
if (arr[i] !== arr[j]) {
return false;
}
}

Trouble solving this coding puzzle using JavaScript

Instructions are as follows:
"Write a function that will find all the anagrams of a word from a list. You will be given two inputs a word and an array with words. You should return an array of all the anagrams or an empty array if there are none. For example:
anagrams('abba', ['aabb', 'abcd', 'bbaa', 'dada']) => ['aabb', 'bbaa']"
I snagged a snippet that takes the first parameter and delivers every combination of characters possible. My trouble now is figuring out how to match this array against the second parameter, and returning some results..
function allAnagrams (word,words) {
if (word.length < 2) {
return [word];
} else {
var allAnswers = [];
for (var i = 0; i < word.length; i++) {
var letter = word[i];
var shorterWord = word.substr(0, i) + word.substr(i + 1, word.length - 1);
var shortwordArray = allAnagrams(shorterWord);
for (var j = 0; j < shortwordArray.length; j++) {
allAnswers.push(letter + shortwordArray[j]);
}
}
return allAnswers;
}
}
allAnagrams("abc",["acb","cba","bac","bca"]);
My instinct was to split the word into an array, and then have another nested for loop to match what needs to be matched. However, I seem to have run into some problems with handling the scope and keep breaking the function so I've turned to you bright minded people. If you have a moment, I would appreciate a hint of how to tackle this from here.
You basically need to see if any permutation of your first string appears in the array.
A fast way to compare if two strings are permutations of one another is to sort the two strings and compare:
function stringSort(string) {
return string.split('').sort().join('');
}
function isAnagram(first, second) {
// are the two sorted strings equal, if so then anagram
return stringSort(first) == stringSort(second);
}
Now, we can use these handy functions to help us build the final desired function:
function allAnagrams(word, words) {
return words.filter(function(element) {
return isAnagram(word, element);
});
}
Note the use of Array#filter, a very handy method for boiling an array down to a few values under some condition.
Note that I have not tested this so if there are any problems please ask.

Javascript: Word reverse function undefined?

I am trying to create a word reverser function that will reverse the letter order of each word in a string, without using any loops.
So far I have this:
var strFlip = function(str){
splitStr = str.split(" ");{
return;
}
var wordFlip = function reverse(splitStr){
return splitStr.split('').reverse().join('');
};
};
console.log(strFlip("Hello Hannah"));
The wordFlip part correctly reverses the order of a single word if used independent of the rest of the code. However, the overall code continually outputs undefined. I am unfamiliar with Javascript, so I assume I am simply not noticing a simple structural issue.
Well, this part causes the function to return immediately, and since it is returning nothing, you get undefined:
var strFlip = function(str){
splitStr = str.split(" ");{
return; //<-- immediately returns here
}
...
};
I'm not sure what that part is trying to do, but to actually do what you want, you can do this:
var strFlip = function(str) {
//Since you are using a variable as a reference to a function
//expression/literal, there is no hoisting so you have to
//predefine
var wordFlip = function reverse(splitStr) {
return splitStr.split('').reverse().join('');
};
return str.split(" ").map(wordFlip).join(" ");
}
A more elegant approach would be to forgo wordFlip and just use an anonymous callback to map:
var strFlip = function(str) {
return str.split(" ").map(function(word) {
return word.split("").reverse().join("");
}).join(" ");
}
To understand what map does, let's look at forEach first since map works in a similar manner. When you use array.forEach(callback), the function callback is called for every element in array. It is equivalent to the following code:
var array = [1, 2, 3];
for(var i = 0; i < array.length; i++) {
callback(array[i]);
}
Essentially it is a "functional" way of iterating over an array and doing something with each element. map also does this; it iterates over the array as well, but converts (maps) each element of the array to something else and returns a new array consisting of the mapped elements. The something else is defined by the behavior of callback. Here's an example that is similar to the example above. Here I'm specifying an actual callback as well so that you can see the behavior a little better:
var array = [1, 2, 3];
var squares = [];
function square(num) {
return num * num;
}
for(var i = 0; i < array.length; i++) {
squares[i] = square(array[i]);
}
Here, square is the same as callback and it is called for each element. The return value of square is then used to construct the new array. Using map, you can rewrite the above as:
var squares = array.map(function(num) {
return num * num;
});
Now applying this to the solution, you can see that we are mapping each word in the sentence to its reverse and then joining on the mapped array.
You're overcomplicating things by trying to nest a function inside a function. Create a single function that does both the work of reversing the words and characters:
var flipper = function reverse(splitStr) {
return splitStr.split('').reverse().join('').split(' ').reverse().join(' ');
};
alert(flipper("Hello Hannah"));
You are pretty close, but the code is a little overbusy. Try this:
function reverse(splitStr) {
return splitStr.split('').reverse().join('');
}
console.log(reverse('Hello Hannah'));
I just took the main workhorse out of your code and simplified the function. You were on the right track,
EDIT
If you want to keep the words in place, like Vivin suggested, you can do something like:
function reverse(splitStr) {
var strs = splitStr.split(' ');
var reverseInPlace = [];
for (var i = 0; i < strs.length; i++) {
reverseInPlace.push(strs[i].split('').reverse().join(''));
}
return reverseInPlace.join(' ');
}
console.log(reverse('Hello Hannah'));
One approach would be split the sentence by empty spaces and then reverse and join empty spaces split again by a space then reverse and join with an empty space.
If you do that then:
"Hello Hannah" will be transformed to "olleH hannaH"
Edit: You can define the prototype to string as your own extension for one line solution.
String.prototype.Flip = function() {
return this.split("").reverse().join("").split(" ").reverse().join(" ");
};
var a="Hello Hannah";
alert(a.Flip());

Loop through array checking for indexOf's more simple?

Okay, like the title says. I have a array looking like this:
var hiTriggers = new Array();
hiTriggers = ["hi", "hai", "hello"];
And I'd like to check through it if it finds either of those. I can already achieve this by doing the following:
if(message.indexOf("hi") >= 0) {
// do whatever here!
}
But I'm looking for an more efficient way rather than doing 100 if() checks. Such as loop through an array with the "hiTriggers".
I tried the following:
for(var i; i < hiTriggers.length; i++) {
console.log(hiTriggers[i]); // simply to know if it checked them through)
if(message.indexOf(hiTriggers[i]) >= 0) {
//do stuff here
}
}
Which sadly did not work as I wanted as it does not check at all.
Thanks in advance and I hope I made sense with my post!
Edit; please note that I have 'messaged' already 'declared' at another place.
It doesn't run because you didn't give the i variable an initial value. It is undefined.
Change to use var i=0;:
for(var i=0; i < hiTriggers.length; i++) {
//console.log(hiTriggers[i]); // simply to know if it checked them through)
if(message.indexOf(hiTriggers[i]) >= 0) {
//do stuff here
console.log("found " + hiTriggers[i]);
}
}
Try using a regular expression to match the message. The \b is a word boundary marker, and the words between the | characters are what is being searched for. If any of the words appear in the message, then message.match will return the array of matches, otherwise null.
var pattern = /\b(Hello|Hi|Hiya)\b/i;
var message = "Hello World";
if (message.match(pattern))
{
console.log("do stuff");
}
You can write even simpler using a for in loop:
for(var v in hiTriggers){
if(message.indexOf(hiTriggers[v]) >= 0) {
//do stuff here
console.log("found " + hiTriggers[v]);
}
}
Problem is becoz - you have not initialized your var i, make it var i = 0;
You can try forEach loop.
hiTriggers.forEach(function(e) {
if(message.indexOf(e) >= 0) {
//do sthg here
}
})

Categories