Reputation: 1276
I'm new to JavaScript (I've used python for ~3yrs, and I'm currently trying to pick up the basics of JS syntax.) I am using codewars to facilitate learning.https://www.codewars.com/kata/5bb904724c47249b10000131/train/javascript
This problem gives the prompt
function points(games) {
// your code here
}
The rules are:
if x>y -> 3 points
if x<y -> 0 point
if x=y -> 1 point
My naive approach is to create a function which receives an array as an input and apply a forEach method to every element therein. However, I'm triggering the following error: Uncaught SyntaxError: Unexpected token 'else'
games = ["0:3","1:2","3:2"]
function points(games){
let p = 0;
games.forEach(
function(game){
let x = game.split(':')[0];
let y = game.split(':')[1];
if(x>y){
p = p + 3};
else if(x=y){
p = p + 1};
else {
p = p + 0;
};
});
};
I'd like to better understand (A) why this error is beginning triggered and (B) what is the right way to accomplish this effect.
Edit: I likely need to cast x and y as a numeric type, however this isn't triggering the current error.
Upvotes: 0
Views: 182
Reputation: 2224
The error you're getting is caused by the semicolon (;
) that you put at the end if
scopes:
if { ... }; else // unexpected token
LE: also, you have a bug in the second check, you're assigning the value of y
to x
. In Javascript comparisons are done with ==
or ===
.
To expand a bit on equality comparisons:
==
will attempt to cast the values before performing the comparison (eg: 1 == '1' => true)
===
is a strict comparison operator that will only return true if both operands are of the same type and value (eg: 1 === 1 => true, 1 === '1' => false)
Here's a working example of your code:
function points(games) {
let p = 0;
games.forEach((game) => {
let x = game.split(':')[0];
let y = game.split(':')[1];
if(x > y) {
p = p + 3;
} else if(x === y) {
p = p + 1;
} else {
p = p + 0;
}
});
};
Below you'll find some other examples.
function points(coordinates) {
let p = 0;
coordinates.forEach((coordinate) => {
const [x, y] = coordinate.split(':');
if(x > y) {
p = p + 3;
} else if(x === y) {
p = p + 1;
}
});
return p;
};
const points = (coordinates) => coordinates
.map(coordinate => coordinate.split(':'))
.reduce((points, [x, y]) => {
if (x > y) { return points + 3; }
if (x === y) { return points + 1; }
return points;
}, 0);
Upvotes: 0
Reputation: 53597
Some things to know about JS when you're coming from Python: the modern Array type has a lot of utility functions, so the code you've written can be done with just a few calls, and a ternary (which I really wish Python supported, like every other modern language)
function score(games = []) {
// we could manually sum values, or we can use reduce() to do that for us.
return games.reduce( (tally, game) => tally + calculateScore(game), 0);
}
/**
* fun fact about JS: functions are "hoisted" i.e. they all get "moved"
* during initial read-in to the top of the file, with their ordering
* made entirely irrelevant: any function can have a function body that
* calls any other function, because they're all at the same declaration level.
*/
function calculateScore(game = "0:0") {
let [x, y] = game.split(":").map(parseFloat);
return x > y ? 3 : x < y ? 0 : 1;
}
This uses some elementary modern JS:
(n+1) - n === 1
no longer holds)Also quite importantly: note that where you see parseFloat
, what really happens is that array.map calls parseFloat
with two arguments: the element, and its index in the array. For parseFloat
, this is fine, because it only takes one argument. However, if you were to naively use parseInt
, things would go horribly wrong: it takes two arguments, namely a string, and a radix.
Upvotes: 2
Reputation: 207531
Your code has a bunch of syntax errors. You are using too many semicolons. You do not add them on every line. You are working with strings and not numbers. You are not going a comparison in your else if, and you do not return anything form the method.
function points(games) {
let p = 0;
games.forEach(
function(game) {
// no reason to do work twice, split once
const parts = game.split(':')
const x = +parts[0]; // convert to a number
const y = +parts[1]; // convert to a number
if (x > y) {
p = p + 3
} else if (x === y) { // comparison is == or === and no semicolon
p = p + 1;
} else { // <-- we do not add semicolons to the blocks on if/else
p = p + 0;
} // <-- we do not add semicolons to the blocks on if/else
});
// your function did not return the calculation total
return p
};
const games = ["0:3", "1:2", "3:2"];
const result = points(games);
console.log(result);
Upvotes: -2
Reputation: 438
forEach is not the best approach for this question. This question can be done with reduce function, which can be used to calculate the accumulated sum for an array.
const games = ["10:3","1:2","3:2", "3:3"]
//forEach approach
function points(games){
let p = 0;
games.forEach(game => {
const [x, y] = game.split(':').map(parseFloat);
x>y? p+=3 : x===y ? p+=1 : p+=0
})
return p
}
//reduce approach
//second parameter in reduce function is the initial value, which is 0 here
function pointsReduce(games){
const sum = games.reduce((accumulate, game) => {
const [x, y] = game.split(':').map(parseFloat);
return accumulate+= x>y? 3 : x===y ? 1 : 0
},0)
return sum
}
console.log(points(games))
console.log(pointsReduce(games))
Upvotes: 1
Reputation: 353
Seems you messed the curly brackets positions. They has to be right before else:
if(x>y){
p = p + 3;
} else if(x=y){
p = p + 1;
} else {
p = p + 0;
};
Upvotes: 0