【问题标题】:Javascript: forEach method within a function?Javascript:函数中的 forEach 方法?
【发布时间】:2020-08-01 06:53:58
【问题描述】:

我是 JavaScript 新手(我已经使用 python 大约 3 年了,我目前正在尝试学习 JS 语法的基础知识。)我正在使用 codewars 来促进学习。https://www.codewars.com/kata/5bb904724c47249b10000131/train/javascript

这个问题给出提示

function points(games) {
  // your code here
}

规则是:

if x>y -> 3 points
if x<y -> 0 point
if x=y -> 1 point 

我的天真的方法是创建一个函数,该函数接收一个数组作为输入,并将 forEach 方法应用于其中的每个元素。但是,我触发了以下错误: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;
    };
  });
};

我想更好地了解 (A) 为什么开始触发此错误,以及 (B) 实现此效果的正确方法是什么。

编辑:我可能需要将 x 和 y 转换为数字类型,但这不会触发当前错误。

【问题讨论】:

  • 您的代码中缺少}
  • }; developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 上的语法,你是在做赋值,而不是比较。
  • @epascarello 不确定您的评论试图指出什么:; 这里当然不需要,但它也不是“错误的”:它什么也不做。当然,放一个很傻,但是if (x) { ... } ;;;;;;;;;;if (x) { ... } 完全一样:孤立的分号只是一个无用的。
  • @Mike'Pomax'Kamermans 它会产生 "Uncaught SyntaxError: Unexpected token 'else'" 所以是的,它确实会产生错误。
  • 啊,在这种情况下,最好提及您评论的各种}; 中的哪个(假设有三个)。跨度>

标签: javascript function if-statement foreach


【解决方案1】:

当您来自 Python 时,需要了解一些关于 JS 的事情:现代 Array 类型有 a lot of utility functions,因此您编写的代码只需几个调用和一个三元(我 真的希望像其他所有现代语言一样支持 Python)

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;
}

这使用了一些基本的现代 JS:

  • default parameters,和你在 Python 中使用的基本一样,
  • arrow functions,有点像 lambda,但也与它们完全不同。但是,如果您想编写现代 JS,了解它们非常重要。
  • array.reduce,这可以使求和值更容易或更难,具体取决于您的代码变得多么复杂,
  • parseFloat 将字符串转换为浮点数(有趣的事实:JS 中的每个数字都是浮点数,这就是为什么整数只能达到 2^53:超过 (n+1) - n === 1 不再成立)
  • ternary operator,这是 Python 非常缺乏的。

同样重要的是:请注意,在您看到parseFloat 的地方,真正发生的是array.map 使用两个参数调用parseFloat:元素及其在数组中的索引。对于parseFloat,这很好,因为它只需要一个参数。然而,如果你天真地使用parseInt,事情就会大错特错:it takes two arguments,即一个字符串和一个基数。

【讨论】:

  • 很好的答案,但实际上并没有在他们的代码中回答用户的问题。
  • 确实如此,通过教他们如何编写现代 JS,这显然是他们从 Python 转向 JS 的意图。特别是对于 JS,并不是每个代码答案都是“通过尽可能多地保留帖子的代码来解决代码问题”,有时(哎呀,经常)它是“教他们如何编写现代代码”。
  • @Mike'Pomax'Kamermans - 谢谢!括号对我来说是新事物,让我陷入了循环。感谢您指出一些最佳做法:)
【解决方案2】:

forEach 不是解决这个问题的最佳方法。这个问题可以用reduce函数来完成,它可以用来计算一个数组的累加和。

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))

【讨论】:

  • 记住:拆分字符串会产生字符串,这意味着 10 将被视为小于 2。
【解决方案3】:

似乎你弄乱了大括号的位置。他们必须先正确:

 if(x>y){
      p = p + 3;
    } else if(x=y){
      p = p + 1;
    } else {
      p = p + 0;
    };

【讨论】:

  • 仍然无法正常工作。您复制了另一个错误
  • 嗯,不算数?
【解决方案4】:

您遇到的错误是由您放在末尾的分号 (;) if 作用域引起的:

if { ... }; else // unexpected token

LE:另外,您在第二次检查中有一个错误,您将y 的值分配给x。在 Javascript 中,比较是使用 ===== 完成的。

扩展一下相等比较:

  • == 将在执行比较之前尝试转换值(例如:1 == '1' => true)

  • === 是一个严格的比较运算符,仅当两个操作数的类型和值相同时才会返回 true(例如:1 === 1 => true, 1 === '1' =>假)

这是您的代码的一个工作示例:

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;
    }
  });
};

您将在下面找到一些其他示例。

  1. 使用数组展开并删除总和为 0 的分支
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;
};
  1. 在可读性方面我最喜欢的方法:
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); 

【讨论】:

    【解决方案5】:

    您的代码有一堆语法错误。您使用了太多分号。您不会在每一行都添加它们。您正在使用字符串而不是数字。您不会在 else if 中进行比较,并且您不会从方法中返回任何内容。

    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);

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-17
      • 2016-04-17
      • 2018-04-20
      • 2017-08-14
      • 2018-04-07
      • 1970-01-01
      • 2021-03-25
      相关资源
      最近更新 更多