my aim is to test for a palindrome (word is the same forwards and backwards) and the log and array containing only the palindromes, so far this is the most I could come with.
const getAllPalindromes = (words) => {
return words.filter((word) => {
word.split("").reverse().join("") === word;
});
};
console.log(getAllPalindromes(["hello", "noon"]));
To my understanding this should return an array containing the items that are true from the boolean, any pointers will help a newbie thanks a lot!
You're not returning your filter conditional. You do the comparison, but then don't return it so the filter has an undefined as the return of the comparator, and thus it doesn't filter anything. Otherwise, the rest of your logic is correct!
const getAllPalindromes = (words) => words.filter((word) => word.split("").reverse().join("") === word);
console.log(getAllPalindromes(["hello", "noon"]));
Since you're using Arrow Functions we're going to use the implicit return in them to make things a little smaller especially since each function is really just a single statement. Here's the same code in a longer format for direct comparison
const getAllPalindromes = function (words) {
return words.filter(function (word) {
return word.split("").reverse().join("") === word;
});
};
console.log(getAllPalindromes(["hello", "noon"]));
The differences between Arrow Functions and Functions was already answered a long time ago, so here it is for reference.
It might also help if you use an editor or code linter that can help you catch the problems early. A missed return statement is just as easy to make as an off by one error.
Off by One errors are as easy to make as a missed return statement undefined
Happy coding!
Related
I was doing this kata on codewars. The question wants the function to return true if the first argument (string) passed in ends with the 2nd argument (also a string). So I wrote my function and everything worked just fine until it compares ':-)' with ':-(' and returns true.
What is wrong? I'm so confident that my code should work that I don't even know what to search for.
function solution(str, ending){
if (!ending) return true; // if ending is a empty string return true (the question wants that)
let ok;
const strArr = str.split(''), endingArr = ending.split('');
for (let i = 0; i < endingArr.length; i++) strArr.reverse()[i] === endingArr.reverse()[i] ? ok = true : ok = false;
return ok;
}
console.log(solution(":-)",":-("));
Your problem is a misunderstanding of what reverse() does. It does not return a reversed copy of the old array, it reverses the existing array and returns that same array. As a result, you keep reversing the arrays back and forth every iteration of the loop, causing some elements to be skipped and some to be checked twice.
Array.prototype.reverse() on MDN
Edit:
As pointed out by others in the comments, both to the question and this answer, there are in fact multiple problems.
reverse() aside, the loop always sets ok to the result of the last comparison, making the function ignore all previous results.
The easier way to implement this is to remove ok altogether. Instead, return false as soon as a mismatch is detected. If the function runs long enough to exit the loop, it means no mismatch was detected and true can be returned.
Edit 2:
Just as a friendly suggestion:
While both reverse() and ok are real issues with the code, I only noticed the first one the first time around due to the formatting of the code. The ok problem was off-screen due to the line being too long. As such, once I spotted the reverse() issue, I assumed that was it and didn't bother scrolling sideways to see the rest of the code.
I am not going to demand that you write your own code in a certain way, but if you format it properly, it allows others to read it more easily. In essence, you help us to more easily help you.
For instance, this line:
for (let i = 0; i < endingArr.length; i++) strArr.reverse()[i] === endingArr.reverse()[i] ? ok = true : ok = false;
...would have been significantly easier to read as...
for (let i = 0; i < endingArr.length; i++) {
if(strArr.reverse()[i] === endingArr.reverse()[i])
ok = true;
else
ok = false;
}
...or some variation thereof. Here, the problem is significantly more visible and obvious.
The other answer explains many of the mistakes you've made. I wanted to point out just how much you've over-thought your solution.
function solution(str, ending){
if (ending === "") return true; // if ending is a empty string return true (the question wants that)
return str.endsWith(ending);
}
console.log(solution(":-)",":-("));
console.log(solution("foo",""));
console.log(solution("foo","bar"));
console.log(solution("foobar","bar"));
Even my solution above is overengineered, str.endsWith("") always returns true. So this can be simplified further.
function solution(str, ending){
return str.endsWith(ending);
}
console.log(solution(":-)",":-("));
console.log(solution("foo",""));
console.log(solution("foo","bar"));
console.log(solution("foobar","bar"));
I am curious if there are any good and shorter alternatives in modern JS to replace this kind of checks:
if (someVar === undefined || someVar.length === 0) { ... }
The question came from the current work on some obsolete codebase projects.
UPD: I am interested in arrays and strings atm, but would be also nice to compare different types
Your current code looks fine to me, but you can also alternate with the empty array and check its length:
if ((someVar || []).length === 0) {
// ...
}
You could take toString() and check the value for falsyness.
function check(v) {
if (!v || !v.toString()) console.log('empty');
}
check();
check([]);
check('');
So im assuming somVar is an array...
Functional programming is a great way to handle these kinds of things without even having if statements, I dont know what kind of "work" you need to do on the structure but lets assume some filtering mapping and reducing it to a value.
So having a function that will handle the someVar will make sure to handle the undefined case and then it will just be an empty array will will be reduced to a 0.
function handleSomeVar(someVar = []) {
return someVar && someVar
.filter(x => x.something) //lets assume we want to be sure this is defined
.map(x => x.something) // we just want an array of primitives number/string/etc
.reduce((memo, somehthing) => something, 0) //making the assumption that the something is a number.
}
or
const handleSomeVar = (someVar = []) => someVar && someVar
.filter(x => x.something)
.map(x => x.something)
.reduce((memo, something) => something, 0)
implicit return arrow functions are the hardest workers in functional programming (imo)
So then result will be a something, unless someVar is empty and then it will return 0. Reduce is a great way to handle these kinds of instances where things might exist or then might not in the case of nothing well then just return the initial value.
Functional programming in this way is meaningful, debuggable, and lots of fun!
Well, here goes my first stack overflow post!
Hello everyone, I have been learning a lot about functional programming recently. I found some older videos over at funfunfunction which whets my appetite and I've been playing around with them.
My question is… Is there a better/different/preferred way of refactoring this chunk of code:
if ( bodyClasses.contains("first-class") || bodyClasses.contains("second-class") || bodyClasses.contains("third-class") ) {
pages.filter((page) => searchAndReplace( page.postType, ".selector" ));
}
I tried using reduce() but quickly learned I'd need to break the reduce prematurely as soon as the first iteration returned true. I feel like the if statement makes sense here but I'm just curious.
I know it is a small chunk of code without context, but the question is in regards concept and not functionality.
And to anyone that responds, I thank you in advance!
To get away the or, match against .some array values:
if(["first-class", "second-class", "third-class"].some(cls => bodyClasses.contains(cls)))
/*...*/;
and I wouldn't use .filter if you are not doing anything with the returned values, then just use .forEach.
When it comes down to it the || will likely need to be somewhere but maybe we can tuck them away. I like to use predicates in my if clauses to increase readability and create reusable functions.
const hasSupport = classes =>
classes.some(cls => cls === "class1" || cls === "class2" || cls === "class3");
if (hasSupport(bodyClasses)) { ... }
The last part to think about is inside your if statement. That filter will return a new list but you aren't storing the data anywhere. So, if you actually want a new list then store it in a variable:
const supportedPages = hasSupport(bodyClasses)
? pages.filter(...)
: []
If you instead want those side effects then use a forEach loop:
if (hasSupport(bodyClasses) { pages.forEach(...) }
I'm having trouble understanding this piece of Javascript code:
var _ref3 = (0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* () {
if (actualArgs.length === 0) {
const sandbox = yield getValidSandbox(curDir);
// It's just a status command. Print the command that would be
// used to setup the environment along with status of
// the build processes, staleness, package validity etc.
let envForThisPackageScripts = PackageEnvironment.calculateEnvironment(sandbox, sandbox.packageInfo, { useLooseEnvironment: true });
console.log(PackageEnvironment.printEnvironment(envForThisPackageScripts));
} else {
let builtInCommandName = actualArgs[0];
let builtInCommand = builtInCommands[builtInCommandName];
if (builtInCommand) {
builtInCommand(curDir, ...process.argv.slice(3));
} else {
console.error(`unknown command: ${builtInCommandName}`);
}
}
});
What exactly is _ref3 ? a function ? a tuple ? I'm confused
I would not like to read your code for you but i think, with a little help you could understand this code your self. I guess you need help with the various new syntax being used in the code above. I'll try to note down those so that you can understand all of this code yourself.
(0, (_asyncToGenerator2 || _load_asyncToGenerator()).default)(function*{})
This line basically is similar to
(0,x)(function*{})
where x is a function which takes a generator function as an argument.
Whenever you have a line of the form (x,y) it will always return the last value. So in the case of(x,y) it will return y. If its (0,x) it will return x. Thus in code which you posted, the first line will return (_asyncToGenerator2 || _load_asyncToGenerator()).default.
You could now translate the code to
((_asyncToGenerator2 || _load_asyncToGenerator()).default)(function* {})
This means that above code will return a function which takes a generator as argument
If you need more information on generator you could go here
The generator function has attributes like yield. They are pretty useful especially to handle asynchronous operations. It streamlines your code and makes it easy to read. To get more information what yield means, you could go here and here
You could also see some lines like these in the code.
builtInCommand(curDir, ...process.argv.slice(3));
This is basically spread operators being used. Spread operators basically allow an expression to be expanded in places where multiple arguments are expected. You could go here
to know more about spread operators.
Hope you will be able to read the above code yourself after you understand the concepts.
I'm relatively new to Javascript (learned Ruby first) but have been very confused by some strange inconsistencies I've been seeing and I'm trying to figure out what the underlying mechanisms are so I can better understand the language. One of these is that when I'm doing a comparison it shouldn't matter on which side of the === sign the two elements are, but I've seen that happen and don't understand why. Here's the example for a basic function to see if a string is sorted alphabetically or not:
This version always returns true:
function sorted(str) {
var arr = str.split("");
return arr.sort().join('') === arr.join('');
}
sorted('abc') // => true
sorted('cba') // => true
While this will return the correct answer:
function sorted(str) {
var arr = str.split("");
return arr.join('') === arr.sort().join('');
}
sorted('abc') // => true
sorted('cba') // => false
I've tried to figure this out and am pretty stuck - can anyone help explain?
Thank you!
Unlike the most of methods of Array.prototype, sort() manipulates the object in place. Hence, in your first snippet arr in the second operand of === is sorted already, and comparison always returns true.