【问题标题】:Evaluate triangle by its side评估三角形的边
【发布时间】:2019-12-06 09:44:24
【问题描述】:

我的问题是关于使用 Javascript 进行三角形评估。以下代码是非常初始的版本,即使它可以工作。我想知道它是否可以更简化或者有其他方法可以达到相同的结果。

谢谢!

let a = Number(prompt('Please input the the first side (a)'))
let b = Number(prompt('Please input the the second side (b)'))
let c = Number(prompt('Please input the the third side (c)'))

if (a + b <= c || b + c <= a || c + a <= b || Number.isNaN(a) || Number.isNaN(b) || Number.isNaN(c) || a == "" || b == "" || c == ""){
  console.log("invalid")
}
else if ((a > 0 && b >0 && c >0 ) && (a == b && b == c && c == a)){
  console.log("equilateral triangle")
}
else if ((a > 0 && b >0 && c >0 ) && (a == b || b == c || c == a)){
  console.log("isosceles triangle")
}
else {
  console.log("scalene triangle")
}

【问题讨论】:

    标签: javascript if-statement logical-operators prompt


    【解决方案1】:

    另一种方法是将长度显式转换为数字(0 表示 NaN)并首先对其进行排序。三元运算符在这里也很有用:

    let [d, e, f] = [a, b, c].map(a => +a || 0).sort((a, b) => a-b);
    let result = d + e <= f     ? "invalid"
               : d === f        ? "equilateral"
               : d < e && e < f ? "scalene"
                                : "isosceles";
    console.log(result);
    

    在执行数千个时,这不会是最快的,但我喜欢它的外观。

    说明

    [a, b, c] 将三个值转换为array

    .map 是一种可用于数组的方法。对于[a, b, c] 中的每个原始值,执行以下(箭头)函数,

    a => +a || 0
    

    map 创建一个新数组,其中包含对每个单独值调用该函数的结果(因此首先使用a,然后使用b,最后使用c

    +a 使用unary plus 作为将值转换为数字的快捷方式,这意味着您可以省略在代码的前三行中进行的Number() 调用。当结果为NaN 或 0 时,|| 0 将生效:而不是 NaN 或 0,取而代之的是 0(|| 是逻辑 OR 运算符,只有在左侧被认为是“虚假的”)。这实际上意味着 NaN 被 0 替换。

    所以到目前为止,代码大致做了类似下面的事情:

    let newarray = [];
    newarray[0] = +a;
    if (Number.isNaN(newarray[0])) newarray[0] = 0;
    newarray[1] = +b;
    if (Number.isNaN(newarray[1])) newarray[1] = 0;
    newarray[2] = +c;
    if (Number.isNaN(newarray[2])) newarray[2] = 0;
    

    然后在.map()返回的数组上调用另一个数组方法:方法.sort()。该方法将使用提供的回调函数(a, b) =&gt; a-b 在数组中进行比较,并根据此类调用返回的值对其进行排序。由sort 方法决定调用该函数的对。当返回值为负数时,表示比较的值已经按升序排列。当为阳性时,应重新排列它们。当为零时,它们应该被认为等于排序算法。

    所以...我们现在有一个由数字组成的数组,这些数字保证不再有NaN,并且按升序排序。

    然后使用所谓的destructuring分配该数组:

    let [d, e, f] =
    

    这意味着已排序数组的各个值被一一分配到三个新变量。所以这大致是:

    let d = new_sorted_array[0];
    let e = new_sorted_array[1];
    let f = new_sorted_array[2];
    

    因为这些值现在是有序的,所以我们可以使用它们进行更简单的比较来确定三角形的形状。下面是一个使用ternary operators 链的表达式,它非常类似于if (...) ... else if ... 链。所以:

    let result = d + e <= f     ? "invalid"
               : d === f        ? "equilateral"
               : d < e && e < f ? "scalene"
                                : "isosceles";
    

    ... 是这个的缩写:

    let result;
    if (d + e <= f) result ="invalid"
    else if (d === f) result = "equilateral"
    else if (d < e && e < f) result = "scalene"
    else result = "isosceles";
    

    【讨论】:

    • 非常感谢。如果可能的话,您能否详细解释一下您的解决方案?特别是“.map(a => +a || 0).sort((a, b) => a-b);”我对这部分很好奇。
    • 添加说明。
    • 解释得很清楚。真的很感激!这部分还有一个问题:“: d === f ? "equilateral" Don't we need to code d===f && e===f?
    • 啊哈,好问题!这就是排序的好处发挥作用的地方。如果您知道 d
    【解决方案2】:

    您可以减少大量体积并更改实现:

    1. 您可以让用户输入函数调用
    2. 您可以将输入放入数组中
    3. 您可以使用every 确保每个值都大于0
    4. 可以使用新的Set来去除重复,如果大小为1,则所有边都相同,如果为2,则2边相同,如果为3,则所有边不同

    const getSide = l => Number(prompt(`Please input the the second side (${l})`))
    const sides = [getSide('a'), getSide('b'), getSide('c')]
    
    if (sides.every(el => el > 0)) {
      const size = new Set(sides).size
      if (size === 1) console.log("equilateral triangle")
      else if (size === 2) console.log("isosceles triangle")
      else console.log("scalene triangle")
    } else {
      console.log("invalid")
    }

    测试用例:

    const test = sides => {
      if (sides.every(el => el > 0)) {
        const size = new Set(sides).size
        if (size === 1) console.log("equilateral triangle")
        else if (size === 2) console.log("isosceles triangle")
        else console.log("scalene triangle")
      } else {
        console.log("invalid")
      }
    }
    
    test([0,1,2]) // invalid
    test([NaN,NaN,NaN]) // invalid
    test(['',1,2]) // invalid
    test([3,3,3]) // eq
    test([2,2,3]) // iso
    test([1,2,3]) // sca

    【讨论】:

    • [1, 1, 3] 应该给出“无效”。
    • @trincot 我明白了,我所做的只是简化 OP 的代码,不再添加实现 :)
    猜你喜欢
    • 1970-01-01
    • 2023-01-30
    • 2021-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-19
    • 1970-01-01
    • 2013-12-24
    相关资源
    最近更新 更多