Confirm the ending of a string without using endsWith() - javascript

Aim:
Check if a string (first argument, str) ends with the given target string (second argument, target). This challenge can be solved with the .endsWith() method but I don't want to use it.
A workable solution:
function confirmEnding(str, target) {
return str.slice(str.length - target.length) === target
}
console.log(confirmEnding("Open sesame", "game")); // false
Above is the "SOLUTION". I got frustrated after seeing how simple it was!
However, although my code was very complicated, I still want it to work out.
Below is my code:
function confirmEnding(str, target){
let newStr = str.split('').reverse()
let newTarget = target.split('').reverse()
function matching (newStr, newTarget){
for (let i = 0; i < newTarget.length ; i++){
return (newTarget[i] === newStr[i]) ? true : false
}
}
}
console.log(confirmEnding("Open sesame", "game"))
It print true, but I expect it to be false.
It is very messy; I want to make the loop to continue on and stop when it hits the false.. How can I do that?
Also, I'm not quite sure where and what "return code" should be added at the end of the function.

Here are the issues with your code:
The nested function isn't necessary
The loop should only return false if it finds a difference
If the loop completes without finding a difference, then you can return true
function confirmEnding(str, target){
let newStr = str.split('').reverse()
let newTarget = target.split('').reverse()
for (let i = 0; i < newTarget.length ; i++) {
if (newTarget[i] !== newStr[i]) {
return false;
}
}
return true;
}
console.log(confirmEnding("Open sesame", "game"))
console.log(confirmEnding("Open sesame", "same"))
A more efficient way to solve the problem is with a regex:
function confirmEnding(str, target) {
return new RegExp(`${target}$`).test(str);
}
console.log(confirmEnding("Open sesame", "game"))
console.log(confirmEnding("Open sesame", "same"))

can you use regex? if you know what the ending might look like you can use regex with indexOf to verify. this assumes you are using javascript

Try this out. The code I use here made things more intuitive to me.
function confirmEnding(str, target) {
let result = str.slice(-target.length);
if (result === target) {
return true} else {
return false}
}

Related

How to find whole substring in string?

I have a string and I have to check if that string contains defined substring I need to do some work and otherwise, I should return some error.
I have the following code:
function isContains(myString) {
let subString = 'test1234';
if(myString.includes(subString)) {
// to do some work
} else {
// return some error.
}
}
but the problem is if myString = 'my-string-test1-rrr' its condition return true.
How can I get true only in case when the whole subString was included in myString?
Use indexOf() instead.
function isContains(myString) {
let subString = 'test1234';
if(myString.indexOf(subString) > -1) {
// to do some work
} else {
// return some error.
}
}
you can use regex to check if that value is present are not;
example 1
without containing the specific string
var test = 'my-string-test1-rrr';
console.log(' test --- ', test.match(/test1234/g))
example 2
contains the specific string
var test = 'my-string-test1234-rrr';
console.log(' test --- ', test.match(/test1234/g))
It is highly recommended to use includes() over indexOf() and further indexOf returns the index of the occurrence where you would prefer an immediate answer - false / true if that substring is found inside the searched string.
Your function does exactly what you are asking. I would suggest to isolate the retrieval of this function and make it purer like so, then when you have the return boolean value you could utilize it after to run whatever logic you wish. This way you keep this function pure and separate your concerns better.
I also believe it would be easier for you to debug your issue if you isolate this functions like In the example I provided.
function isContains(myString) {
let subString = 'test1234';
let isContains = false;
if(myString.includes(subString)) {
isContains = true;
} else {
isContains = false;
}
return isContains;
}
You could use it like so in a later phase in your code:
const myString = 'my-string-test1-rrr';
let shouldRunOtherLogic = isContains(myString);
if (shouldRunOtherLogic) {
// to do some work
} else {
// return some error.
}
Hope I could help, if there's anything further you may need feel free to let me know.

Different output in a function and outside it

It is one of the beginner challenges for javascript, where you need to check whether the passed parameter(string of symbols, namely =, +, any letter) to a function, includes a random letter surrounded by +. If there is one, return true, else - false.
function simple(str) {
let alph = 'abcdefghijklmnopqrstuvwxyz';
let alphArray = alph.split('');
for (let i = 0; i <= alphArray.length; i++) {
if (str.includes(`+${alph[i]}+`)) {
return true;
} else {
return false;
}
}
}
console.log(simple('+d+=3=+s+'));
It should return true, but I am certainly missing something, most likely it's the condition.
Also, tried doing it without a function, with a predefined variable with the given symbols and it worked, but a in a sloppy way.
You need to move the false return statement outside of the loop, because this would end the loop immediately without checking the following possible true values and need to have the index smaller as the length of the string.
BTW, no need to use an array.
function simple(str) {
let alph = 'abcdefghijklmnopqrstuvwxyz';
for (let i = 0; i < alph.length; i++) {
if (str.includes(`+${alph[i]}+`)) {
return true;
}
}
return false;
}
console.log(simple('+d+=3=+s+'));

Run one value through multiple functions (Javascript)

I want to create a function "palindromes()" which checks whether a value is a palindrome (spelled the same forwards and backwards).
In order to do that, I have created 4 functions, which:
Makes all letters small
Removes all non-letter characters
Reverses the ensuing array, and finally...
Checks whether that array is a palindrome.
See functions bellow:
function makeSmall(input) {
lowerCase = input.toLowerCase();
return lowerCase;
}
function keepOnlyLetters(input) {
var patt1 = /[a-z]/g;
var onlyLetters = input.match(patt1);
return onlyLetters;
}
function reverseArray(array) {
var reversedArray = array.slice().reverse();
return reversedArray;
}
function checkPalindromes(array) {
var reversedArray = array.slice().reverse();
for (let i = 0; i <= array.length; i++) {
if (array[i] != reversedArray[i]) {
return false;
}
}
return true;
}
How do I make sure that the function "palindromes()" takes one value and runs it through all these functions to finally give me an answer (true or false) of whether that value is a palindrome or not?
Best regards,
Beni
There's a point of diminishing returns with functions. When calling the function is just as short as using the body of the function inline, you've probably hit that point. For example, makeSmall(input) is really no improvement to just using input.toLowerCase() inline and will be slower and harder to understand. input.toLowerCase() is already a function; it's just wasted work to wrap it in another function.
Having said that, to answer your question, since all your functions return the value that's input to the next, you can put you functions in an array and call reduce():
function palindromes(input) {
return [makeSmall, keepOnlyLetters, reverseArray, checkPalindromes].reduce((a, c) => c(a), input)
}
So first before trying to do composition at first it sometimes works best to do it sequentially to make sure you understand the problem. As you get better at composition eventually you'll know what tools to use.
function checkPalindrome(string){
return string
.toLowerCase()
.match(/[a-z]/g)
.reverse()
.reduce(function ( acc, letter, index ) {
return acc && string[index] == letter
})
}
checkPalindrome('test') // false
checkPalindrome('tet') // true
Okay good we understand it procedurally and know that there are four steps. We could split those four steps out, however since two steps require previous knowledge of the array state and we don't want to introduce converge or lift just yet we should instead just use a pipe function and combine the steps that require a previous state. The reason for that is eventually functions just lose how much smaller you can make them, and attempting to split those steps up not only hurts readability but maintainability. Those are not good returns on the effort invested to make two functions for that part!
function pipe (...fns){
return fns.reduce( function (f, g){
return function (...args){
return g(
f(...args)
)
}
}
}
All this function does it it pre-loads(composes) a bunch of functions together to make it so that the output of one function applies to the input of the next function in a left to right order(also known as array order).
Now we just need out three functions to pipe:
function bringDown(string){ return string.toLowerCase() } // ussually called toLower, see note
function onlyLetters(string){ return string.match(/[a-z]/g) }
function flipItAndReverseItCompare(arrayLike){ // I like missy elliot... ok?
let original = Array.from(arrayLike)
return original
.slice()
.reverse()
.reduce(function (acc, val, ind){
return acc && val == original[ind]
})
}
Now we can just pipe them
let palindrome = pipe(
bringDown,
onlyLetters,
flipItAndReverseItCompare
)
!palindrome('Missy Elliot') // true... and I never will be
palindrome('Te t') // true
Now you're well on your way to learning about function composition!
You can just string the function calls together like this...
var input = 'Racecar';
if (checkPalindromes(reverseArray(keepOnlyLetters(makeSmall(input))))) {
alert("It's a palindrome");
}
You can just call them in a nested fashion and return the final result in your palindrome function.
Sample Code: (with changes indicated in the comments)
function makeSmall(input) {
// Added var to prevent it from being a global
var lowerCase = input.toLowerCase();
return lowerCase;
}
function keepOnlyLetters(input) {
var patt1 = /[a-z]/g;
var onlyLetters = input.match(patt1);
return onlyLetters;
}
// This function is not really needed and is unused
/*function reverseArray(array) {
var reversedArray = array.slice().reverse();
return reversedArray;
}*/
function checkPalindromes(array) {
var reversedArray = array.slice().reverse();
for (let i = 0; i <= array.length; i++) {
if (array[i] != reversedArray[i]) {
return false;
}
}
return true;
}
// New Palindromes function
function palindromes(input){
return checkPalindromes(keepOnlyLetters(makeSmall(input)));
}
Note:
You don't really need so many functions to do this. I'm putting this here as a strict answer to your exact question. Other answers here show how you can solve this in shorter (and better?) ways
try the following snippet.
function makeSmall(input) {
lowerCase = input.toLowerCase();
return lowerCase;
}
function keepOnlyLetters(input) {
var patt1 = /[a-z]/g;
var onlyLetters = input.match(patt1);
return onlyLetters;
}
function reverseArray(array) {
var reversedArray = array.slice().reverse();
return reversedArray;
}
function checkPalindromes(array) {
var reversedArray = array.slice().reverse();
for (let i = 0; i <= array.length; i++) {
if (array[i] != reversedArray[i]) {
return false;
}
}
return true;
}
var result = checkPalindromes(reverseArray(keepOnlyLetters(makeSmall("Eva, Can I Stab Bats In A Cave"))));
console.log(result);
Notice how functions are called one after the other in one line.

How to find the missing next character in the array?

I have an array of characters like this:
['a','b','c','d','f']
['O','Q','R','S']
If we see that, there is one letter is missing from each of the arrays. First one has e missing and the second one has P missing. Care to be taken for the case of the character as well. So, if I have a huge Object which has all the letters in order, and check them for the next ones, and compare?
I am totally confused on what approach to follow! This is what I have got till now:
var chars = ("abcdefghijklmnopqrstuvwxyz"+"abcdefghijklmnopqrstuvwxyz".toUpperCase()).split("");
So this gives me with:
["a","b","c","d","e","f","g","h","i","j","k","l","m",
"n","o","p","q","r","s","t","u","v","w","x","y","z",
"A","B","C","D","E","F","G","H","I","J","K","L","M",
"N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
Which is awesome. Now my question is, how do I like check for the missing character in the range? Some kind of forward lookup?
I tried something like this:
Find the indexOf starting value in the source array.
Compare it with each of them.
If the comparison failed, return the one from the original array?
I think that a much better way is to check for each element in your array if the next element is the next char:
function checkMissingChar(ar) {
for (var i = 1; i < ar.length; i++) {
if (ar[i].charCodeAt(0) == ar[i-1].charCodeAt(0)+1) {
// console.log('all good');
} else {
return String.fromCharCode(ar[i-1].charCodeAt(0)+1);
}
}
return true;
}
var a = ['a','b','c','d','f']
var b = ['O','Q','R','S']
console.log(checkMissingChar(a));
console.log(checkMissingChar(b));
Not that I start to check the array with the second item because I compare it to the item before (the first in the Array).
Forward Look-Ahead or Negative Look-Ahead: Well, my solution would be some kind of that. So, if you see this, what I would do is, I'll keep track of them using the Character's Code using charCodeAt, instead of the array.
function findMissingLetter(array) {
var ords = array.map(function (v) {
return v.charCodeAt(0);
});
var prevOrd = "p";
for (var i = 0; i < ords.length; i++) {
if (prevOrd == "p") {
prevOrd = ords[i];
continue;
}
if (prevOrd + 1 != ords[i]) {
return String.fromCharCode(ords[i] - 1);
}
prevOrd = ords[i];
}
}
console.log(findMissingLetter(['a','b','c','d','f']));
console.log(findMissingLetter(['O','Q','R','S']));
Since I come from a PHP background, I use some PHP related terms like ordinal, etc. In PHP, you can get the charCode using the ord().
As Dekel's answer is better than mine, I'll try to propose somewhat more better answer:
function findMissingLetter (ar) {
for (var i = 1; i < ar.length; i++) {
if (ar[i].charCodeAt(0) != ar[i-1].charCodeAt(0)+1) {
return String.fromCharCode(ar[i-1].charCodeAt(0)+1);
}
}
return true;
}
var a = ['a','b','c','d','f']
var b = ['O','Q','R','S']
console.log(findMissingLetter(a));
console.log(findMissingLetter(b));
Shorter and Sweet.

Javascript: Palindrome function undefined?

I have been working on a palindrome function (will check if word is spelled the same forward and backwards):
var palinDromes = function(palMap) {
palMap.split(" ").map(function(word) {
var palCheck = (word.toLowerCase() === word.toLowerCase().split("").reverse().join(""));
return palCheck;
});
};
console.log(palinDromes('Hannah speaks English and Malayalam'));
But the output is always undefined. I believe the issue is in the first step, something involving the console.log(palinDrome(...)); transition to palMap, but I'm not sure what exactly.
The issue might also be that I am not returning palCheck correctly at the end of the function?
var palinDromes = function(palMap) {
return palMap.split(" ").map(function(word) {
var palCheck = (word.toLowerCase() === word.toLowerCase().split("").reverse().join(""));
return palCheck;
});
};
console.log(palinDromes('Hannah speaks English and Malayalam'));
EDIT: I added a return before palMap.split(" ").map(function(word) { ...

Categories

Resources