I am looking at using a switch statement to check if an array's length is greater than 0. I could do this using an if/else statement but I want to get more comfortable using switch statements and am slightly baffled why the following doesn't work.
Given an array of numbers, my function determines whether the sum of all of the numbers is odd or even.
Here is what it looks like:
function oddOrEven(array) {
switch(array) {
case array.length === 0:
throw 'Error';
break;
case array.length > 0:
answer = array.reduce((a, b)=>{
return a + b;
}) % 2 === 0 ? 'even' : 'odd';
break;
}
}
examples
oddOrEven([0]) returns "even"
oddOrEven([2, 5, 34, 6]) returns "odd"
oddOrEven([0, -1, -5]) returns "even"
I know I can do if(array.length > 0)... but as I said I want to get used to using switch statements and thought that this should also work.
With switch, you compare an expression to values, doing an action for each one. In your case, you could switch the array.length like that:
function oddOrEven(array) {
switch(array.length) {
case 0:
throw 'Error';
break;
default: // in that case, array.length != 0, not > 0 necessarily
answer = array.reduce((a, b)=>{
return a + b;
}) % 2 === 0 ? 'even' : 'odd';
break;
}
}
However, in my opinion, if/else is the right one to be used here. It is worth to take a look at MDN documentation for switch to understand the best scenarios in which it can be used.
The idiomatic usage of the switch statement would be as follows:
switch(array.length) {
case 0: // ...
default: // ...
}
However, you are right in assuming that expressions can be used instead of values in the case labels. The following will work:
function oddOrEven(array) {
switch (true) {
case array.length === 0:
throw 'Error';
case array.length > 0:
return array.reduce((a, b) => a + b) % 2 === 0 ? 'even' : 'odd';
}
}
console.log(oddOrEven([0]));
console.log(oddOrEven([2, 5, 34, 6]));
Obviously, using an if statement is the more readable approach in this case.
I don't think it's a good practice to do switch statements to check an array length. You should rather do it like this:
function oddOrEven(arr) {
if(arr.length === 0) {
throw 'Error';
}
return array.reduce((a, b)=>{
return a + b;
}) % 2 === 0 ? 'even' : 'odd';
}
Related
I have a function to check sums in an array :
function checkSum(array, sum) {
// array = [1,4,6,11] sum = 10
var answers = [];
var map = new Map();
for (var x = 0; x < array.length; x++) {
if (map.has(array[x])) {
answers.push([sum - array[x], array[x]])
} else {
map.set(sum - array[x])
}
}
answers.length != 0 ? console.log(answers) : console.log("nada")
}
I originally had the last line just return answers; but let's say I don't want to return an empty array -- instead, I'd rather just log a statement.
why doesn't a return in a ternary conditional work such as this:
answers.length != 0 ? return answers : console.log("nada")
You need to use return answers.length != 0 ? answers : console.log("nada"). The reason it fails is because ternary conditions do not support return in their conditions. Infact, the ternary operator evaluates to an expression and expressions do not contain a return statement.
function checkSum(array, sum) {
// array = [1,4,6,11] sum = 10
var answers = [];
var map = new Map();
for (var x = 0; x < array.length; x++) {
if (map.has(array[x])) {
answers.push([sum - array[x], array[x]])
} else {
map.set(sum - array[x])
}
}
return answers.length != 0 ? answers : console.log("nada")
}
console.log(checkSum([1, 4, 6, 11], 10));
The ternary (conditional) operator expects the "expr1" part (where return answers is) to be an expression - that is, something that can be evaluated to a value, which can be used in other expressions. But a return statement is a statement, one which cannot possibly be interpreted as value, or as an expression; hence, a syntax error is thrown.
Instead of
answers.length != 0 ? console.log(answers) : console.log("nada")
either use a standard if statement:
if (answers.length !== 0) return answers;
console.log('nada');
or, if you just want to log, put the conditional operator inside the console.log instead:
console.log(
answers.length === 0
? 'nada'
: answers
)
I used ternary operators like this a lot in the past. It's fun, and keeps it to one line.
It can certainly be done, as Ankit shows, by putting the return statement out front
return answers.length != 0 ? answers : console.log('nada')
But I would recommend you use a classic if statement for this. Particularly since you're testing whether to return a value or just log one.
if (answers.length != 0) {
return answers;
};
console.log('nada')
I would go even further and recommend that you return the same value type no matter what. This will go a long way for using your function, well - functionally. In this case, that would involve still returning the array (even if it's empty) and logging the nada as well if empty.
if (answers.length == 0) {
console.log('nada');
};
return answers;
I tried to make an HCF function in javascript using recursive functions as given in the code below. But somehow this only works for exact multiples of numbers (like 2,4 ; 52,104 etc). Co-prime numbers also gives 'undefined'. Please help me fix the bug.
I have tried substituting a local scope variable c = a % b. But this doesn't work out either.
The code:
function hcf(a, b) {
if (b == 1){
return 1;
} else if (a % b == 0){
return b;
} else {
hcf(a,a % b);
}
}
Test cases:
hcf(4,2);
hcf(108,52);
hcf(9,4);
Expected Outcomes:
2
4
1
Actual Outcomes:
2 [Correct]
undefined [Incorrect]
undefined [Incorrect]
The recursive case needs a return statement.
I'm new to JS, and I've having some trouble with this particular code. It is supposed to be a Rock, Paper, Scissors using the switch statement, but it's not returning the draw value and is returning other values wrong:
function RPS(ch1, ch2){
switch (ch1, ch2){
case ('r' && 'p') || ('p' && 'r'):
return 'p';
break;
case ('r' && 's') || ('s' && 'r'):
return 'r';
break;
case ('p' && 's') || ('s' && 'p'):
return 's';
break;
default:
return 'draw';
}
}
console.log(RPS('s', 's'));
So testing with 's' and 's', I was expecting 'draw' but it returned 'r'. What did I do wrong?
Following are mistakes of your code.
You can't have two variables for switch statement. ch1, ch2 will evaluate to ch2.
'r' && 'p' will always evaluate to true. Because both r and p are truthy values.
You can do that in following steps:
Create an object with keys as return values p,q,r. And their values will be the array of two values for which you want to checking in the original code. For example p will have array ['r','p']
You Object.entries on the object. And use find() on entries.
Inside find() put the values ch1 and ch2 in array in both order i.e [ch1,ch2] and [ch2,ch1]
Check if any of the array is equal to any of value of object using every()
If yes then return the key otherwise return 'draw'
function RPS(ch1, ch2){
const obj = {
p:['r','p'],
r:['r','s'],
q:['p','s']
}
let entry = Object.entries(obj)
.find(([k,v]) =>
[ch1,ch2].every((x,i) => x === v[i]) ||
[ch2,ch1].every((x,i) => x === v[i])
)
return entry ? entry[0] : 'draw';
}
console.log(RPS('s','p'))
Maybe I'm asking google all the wrong questions but I scoured the internet and could not find posts similar to my unique problem.
This is a simple coding challenge from FreeCodeCamp:
I need to work on the function abTest(a,b) where when a OR b is less than 0, the function will exit with the value of undefined. This is because we run the value a and b through a square root function. And you cannot take the square root of a negative number. Below is the code.
// Setup
function abTest(a, b) {
if (a < 0) {
a = -a;
return undefined;
} else if (b < 0) {
b = -b;
return undefined;
}
return Math.round(Math.pow(Math.sqrt(a) + Math.sqrt(b), 2));
}
// Change values below to test your code
abTest(2,2);
This code I used above works fine. However I have to specify that when a or b is < 0, a is assigned -a and b is assigned -b. Why is this necessary? In addition I want to convert this into a Switch statement, but I run into this problem of negative num values. Below are two switch statements I wrote but when using negative num input the abTest(-2,2) or abTest(2,-2) does not return the value undefined.
My First Switch Statement
switch (a,b) {
case a<0 || b<0:
return undefined;
}
My Second Switch Statement
switch (a,b) {
case a < 0:
a = -a;
console.log(undefined);
break;
case b < 0:
b = -b;
console.log(undefined);
break;
}
Where is this hole in my logic concerning switch statements and negative num values?
Thank you guys,
There should be no need to convert a = -a unless there is something wrong with freecodecamp. Just returning the value of undefined would/should produce the exact same result as changing a variable and then still returning undefined. To simplify your code you could also combine the if and else if statements like so
function abTest(a, b) {
if (a < 0 || b < 0){
return undefined;
} else {
return Math.round(Math.pow(Math.sqrt(a) + Math.sqrt(b), 2));
}
}
hope this helps
Primordial topic, I know, but can anyone please comment on the following algorithm for comparing two ES5 arrrays:
function equal_arrays(a, b) {
"use strict";
var c = 0;
return a.every(function (e) {
return e === b[c++];
});
}
I think this is very clean and obvious use of [].every(), to quickly compare two arrays?
I have that nagging "surely it can not be that simple ?" feeling about it ?
NOTE: two arrays are equal when they contain all elements in the same position strictly equal to each other. So both the element index and element value have to be exactly equal. Values of different types are considered not equal. Sparse arrays are also compared.
TEST CASES:
equal_arrays([],[]) ; // => true
equal_arrays([1,2],[1,2]) ; // => true
equal_arrays([1,,2],[1,,2]) ; // => true
equal_arrays([,],[,]); // => true
equal_arrays([1,,3,,,],[1,,3,,,]); // => true
Uses cases yielding => false, one can imagine herself. Comparing non-arrays is a syntax error.
Many thanks to the well meaning and helpful contributors. It appears that the "best" (there is never such a thing) implementation is this:
function has(element, index)
{
return this[index] === element;
}
function equal_arrays(a, b)
{
return (a.length === b.length) && a.every(has, b) && b.every(has, a);
}
#tom's implementation of the two-way every() which is necessary sp that test cases like this one work:
equal_arrays([1,,3],[1,2,3]); //=> false
Once again thanks ...
No, it is not valid. From the MDN docs:
callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
So if the first array has 'gaps' they will be skipped over.
equal_arrays([1, 2, , 4], [1, 2, 4]); // true
equal_arrays([1, 2, 4], [1, 2, , 4]); // false
Here is a better implementation:
function equal_arrays(a, b) {
if (a.length != b.length) return false;
var i;
for (i = 0; i < a.length; i++) {
if (a[i] !== b[i]) return false;
}
return true;
}
Here is an elegant implementation of #RobG's two-way every() idea:
function has(element, index)
{
return this[index] === element;
}
function equal_arrays(a, b)
{
return (a.length === b.length) && a.every(has, b) && b.every(has, a);
}
I have that nagging "surely it can not be that simple ?" feeling about it ?
No, it isn't. Using every on one array will test it for every member of that array but not the other. You have to test both ways.
Also, it depends on your criteria for "equal". You might want every member of the same index to have the same value, but you might not be concerned about order so is [1,2] equal to [2,1]? and is [,,,2] equal to [2]?
Also, should [1,,2] equal [1,undefined,2], i.e. should a member that doesn't exist be "equal" to one that does but has the value undefined?
An array comparison function
The following may do the job. It compares both ways, checking own properties and values. I think it covers all cases but am willing to be convinced otherwise. Might be better as a separate function, but adding to Array.prototype is convenient.
// Test that own properties of two arrays have the same values
Array.prototype.isEqualTo = function(a) {
var visited = {};
if (this.length != a.length) return false;
// Test every own property of this, remember tested properties
for (var p in this) {
if (this.hasOwnProperty(p)) {
visited[p] = p;
if (!(a.hasOwnProperty(p)) || this[p] !== a[p]) {
return false;
}
}
}
// Reverse test that comparison array only has tested properties
for (var q in a) {
if (a.hasOwnProperty(q) && !(q in this)) {
return false;
}
}
return true;
}
console.log([1,,2].isEqualTo([1,undefined,2])); // false, not defined != undefined
console.log([1,,2].isEqualTo([1,2])); // false, different length
console.log([1,2].isEqualTo([1,2])); // true
Note that inherited properties should be ignored as if arrays from different windows are compared (e.g. one is from a frame) then inherited properties won't be equal.
As an alternative, if you just want to check if both arrays are exactly the same you could just do this:
var a = [1,2,3,4];
var b = [1,2,3,4];
JSON.stringify(a) == JSON.stringify(b); //= true
That should work with arrays of numbers and strings.
As CrazyTrain said, the increment value is useless and you need to check for length first:
function equalArrays( a, b ) {
"use strict";
if (a.length !== b.length) return false;
return a.filter(function(el){ return el;}).every(function(e, i) {
return e === b[i];
});
}
Is a valid algorithm to compare arrays by value.