多个“if语句”的替代方案?

6

我对HTML和Javascript非常陌生。 我很感激您提供的任何帮助来改进我的代码。

我正在开发一个计算器,用于显示机场之间的距离。 用户将有五个“文本”输入框,他们将输入机场代码,例如MAD,JFK。 结果将是马德里和JFK之间的距离。 用户可以添加多个机场,如BCN MAD JFK ORD,结果应为所有行程的总和(结果= BCN-MAD + MAD-JFK + JFK-ORD)。

对于我的目的,重要的是我指定距离(因此我不需要“计算”坐标之间的距离)。

我已经创建了名为“leg1,2,3,4”的变量,每个变量对应一组机场,因此leg1可以是“BCNMAD”,然后使用if语句可以获得该行程距离。 最后有一个totalDistance变量来添加所有行程距离。

由于每个行程都需要单独计算并添加到其他行程中,因此我复制了每个单独行程的if语句。

这似乎有效,但迄今为止我只添加了8个机场。 实际要求将是大约200个机场。 并且由于每个行程都有自己的一组if,我可能会得到约800个IFs。

我想知道是否有更好的方法来完成这项工作? 另外,我不知道可以处理多少个if

就像我之前说过的,我对HTML和Javascript非常陌生,因此我确定还有更好的解决方案,但是我已经被这个问题困扰了几天,而这是我能想到的最佳解决方案。

所以任何建议或帮助将不胜感激。 我已在下面包含了代码。

顺祝商祺, 麦克

function displayDistance()
{
var leg1 = {route:document.getElementById("air1").value + document.getElementById("air2").value , distance:""};
var leg2 = {route:document.getElementById("air2").value + document.getElementById("air3").value , distance:""};
var leg3 = {route:document.getElementById("air3").value + document.getElementById("air4").value , distance:""};
var leg4 = {route:document.getElementById("air4").value + document.getElementById("air5").value , distance:""};

if (leg1.route == "AGPMAD" || leg1.route == "MADAGP") {leg1.distance = 430;}
if (leg1.route == "BCNMAD" || leg1.route == "MADBCN") {leg1.distance = 483;}
if (leg1.route == "LHRMAD" || leg1.route == "MADLHR") {leg1.distance = 1246;}
if (leg1.route == "CDGMAD" || leg1.route == "MADCDG") {leg1.distance = 1065;}
if (leg1.route == "JFKMAD" || leg1.route == "MADJFK") {leg1.distance = 5777;}
if (leg1.route == "ORDJFK" || leg1.route == "JFKORD") {leg1.distance = 1191;}
if (leg1.route == "JFKMCO" || leg1.route == "MCOJFK") {leg1.distance = 1520;}
if (leg1.route == "JFKIAD" || leg1.route == "IADJFK") {leg1.distance = 367;}

if (leg2.route == "AGPMAD" || leg2.route == "MADAGP") {leg2.distance = 430;}
if (leg2.route == "BCNMAD" || leg2.route == "MADBCN") {leg2.distance = 483;}
if (leg2.route == "LHRMAD" || leg2.route == "MADLHR") {leg2.distance = 1246;}
if (leg2.route == "CDGMAD" || leg2.route == "MADCDG") {leg2.distance = 1065;}
if (leg2.route == "JFKMAD" || leg2.route == "MADJFK") {leg2.distance = 5777;}
if (leg2.route == "ORDJFK" || leg2.route == "JFKORD") {leg2.distance = 1191;}
if (leg2.route == "JFKMCO" || leg2.route == "MCOJFK") {leg2.distance = 1520;}
if (leg2.route == "JFKIAD" || leg2.route == "IADJFK") {leg2.distance = 367;}

if (leg2.route == "AGPMAD" || leg2.route == "MADAGP") {leg2.distance = 430;}
if (leg3.route == "BCNMAD" || leg3.route == "MADBCN") {leg3.distance = 483;}
if (leg3.route == "LHRMAD" || leg3.route == "MADLHR") {leg3.distance = 1246;}
if (leg3.route == "CDGMAD" || leg3.route == "MADCDG") {leg3.distance = 1065;}
if (leg3.route == "JFKMAD" || leg3.route == "MADJFK") {leg3.distance = 5777;}
if (leg3.route == "ORDJFK" || leg3.route == "JFKORD") {leg3.distance = 1191;}
if (leg3.route == "JFKMCO" || leg3.route == "MCOJFK") {leg3.distance = 1520;}
if (leg3.route == "JFKIAD" || leg3.route == "IADJFK") {leg3.distance = 367;}

if (leg4.route == "AGPMAD" || leg4.route == "MADAGP") {leg4.distance = 430;}
if (leg4.route == "BCNMAD" || leg4.route == "MADBCN") {leg4.distance = 483;}
if (leg4.route == "LHRMAD" || leg4.route == "MADLHR") {leg4.distance = 1246;}
if (leg4.route == "CDGMAD" || leg4.route == "MADCDG") {leg4.distance = 1065;}
if (leg4.route == "JFKMAD" || leg4.route == "MADJFK") {leg4.distance = 5777;}
if (leg4.route == "ORDJFK" || leg4.route == "JFKORD") {leg4.distance = 1191;}
if (leg4.route == "JFKMCO" || leg4.route == "MCOJFK") {leg4.distance = 1520;}
if (leg4.route == "JFKIAD" || leg4.route == "IADJFK") {leg4.distance = 367;}

  
var totalDistance = leg1.distance + leg2.distance + leg3.distance + leg4.distance;
  
document.getElementById("distanceresult").innerHTML = totalDistance;
}
<span>Route: </span>
<input type="text" class="airinput" id="air1" value="" required=""/>
<input type="text" class="airinput" id="air2" value="" required=""/>
<input type="text" class="airinput" id="air3" value="" required=""/>
<input type="text" class="airinput" id="air4" value="" required=""/>
<input type="text" class="airinput" id="air5" value="" required=""/>
<br/>
<input type="button" onClick="displayDistance();" value="Calculate Distance"/><br/>
<span>The total distance is: </span><span id="distanceresult"></span><br/>


1
不要使用 leg1 ... leg4,而是创建一个数组。遍历它,这样你就可以消除重复的(四倍的)代码。如果这还不够,放弃 if 语句并使用单个 switch - alesc
5个回答

5

不需要复制每个if语句块,你应该将它们转换成一个函数,然后像这样做:

function getLegDistance(route) {
    if (route == "AGPMAD" || route == "MADAGP") return 430;
    if (route == "BCNMAD" || route == "MADBCN") return 483;
    if (route == "LHRMAD" || route == "MADLHR") return 1246;
    if (route == "CDGMAD" || route == "MADCDG") return 1065;
    if (route == "JFKMAD" || route == "MADJFK") return 5777;
    if (route == "ORDJFK" || route == "JFKORD") return 1191;
    if (route == "JFKMCO" || route == "MCOJFK") return 1520;
    if (route == "JFKIAD" || route == "IADJFK") return 367;
}

var totalDistance = getLegDistance(leg1.route) + getLegDistance(leg2.route) + getLegDistance(leg3.route) + getLegDistance(leg4.route)

那样你只需要一个 if 语句块,就可以为每个路由调用它。你也可以使用 switch 语句代替所有的 if 语句,但这并不能减少你的代码行数(虽然会提高性能),因此对象 / 映射可能更好。

谢谢。这很完美运作。我尝试使用 switch,但问题又在于必须重复所有的距离。 - Mike1986

5

不要将数据硬编码到一长串条件语句中,最好使用对象。这样更容易过渡到基于数据库的解决方案,这通常是处理此类问题的方式。

var distances_ = {
  "AGPMAD": 430,
  "MADAGP": 430,
  "BCNMAD": 483,
  "LHRMAD": 1246,
};
leg1.distance =  distances_[ leg1.route ] );

如果您完全使用Javascript,可以使用JSON文本文件和AJAX调用来替代数据库,从代码中完全删除距离数据。

1
谢谢,这正是我正在寻找的。唯一的问题是,除非使用了所有字段,否则我会得到一个结果为"NaN"的距离(因此我不能仅计算单独1或2段的距离)。我通过再次使用if来解决了这个问题:totalDistance = leg1.distance + leg2.distance + leg3.distance + leg4.distance; if (isNaN(totalDistance)) {totalDistance = leg1.distance + leg2.distance + leg3.distance} if (isNaN(totalDistance)) {totalDistance = leg1.distance + leg2.distance} if (isNaN(totalDistance)) {totalDistance = leg1.distance} - Mike1986

2

使用switch语句。

以下是参考资料:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/switch

示例:

switch (expression) {
  case value1:
    //Statements executed when the result of expression matches value1
    [break;]
  case value2:
    //Statements executed when the result of expression matches value2
    [break;]
  ...
  case valueN:
    //Statements executed when the result of expression matches valueN
    [break;]
  default:
    //Statements executed when none of the values match the value of the expression
    [break;]
}

谢谢。我尝试使用switch,但它只适用于一个变量,所以我需要复制距离。因此,我可以使用switch(leg1),但是必须为每个腿重复相同的操作。 - Mike1986
抱歉没有提供更高级的建议,我提供了一个简单的答案,因为你说你是新手。无论如何,最好的问候! - Eduardo Poço

2
这绝对是一个有趣的问题! 我想了解一下解决方案。我发现机场代码中有很多重复,意识到这可能会失控。最好的做法是使用数据结构来指导您的代码而不是让您的代码指导如何存储数据。您可以将所有机场数据存储在一个对象中,并引用该对象以获取距离。我发现了一个常见模式,它可以是[key] [value][value][key]。为了解决这个问题,我使用了 lodash forEach 函数。您可以在此处查看工作情况!如果您有任何问题,请告诉我 :)
function displayDistance() {

    var routes = {
        MAD: {
            AGP: 430,
            BCN: 483,
            LHR: 1246,
            CDG: 1065,
            JFK: 5777,
        },
        JFK: {
            ORD: 1191,
            MCO: 1520,
            IAD: 367,
            MAD: 5777,
        }
    };

    var leg1 = {
        departingCity: document.getElementById("air1").value,
        arrivalCity: document.getElementById("air2").value,
    };

    var leg2 = {
        departingCity: document.getElementById("air2").value,
        arrivalCity: document.getElementById("air3").value,
    };

    var leg3 = {
        departingCity: document.getElementById("air3").value,
        arrivalCity: document.getElementById("air4").value,
    };

    var leg4 = {
        departingCity: document.getElementById("air4").value,
        arrivalCity: document.getElementById("air5").value,
    };

    function getDistance(departingCity, arrivalCity, routes) {
        var distance
        _.forEach(routes, function(_value, key) { 
            if(departingCity ===  key) {
                distance = routes[departingCity][arrivalCity]
            } else if (arrivalCity === key) {
                distance = routes[arrivalCity][departingCity]
            } 
        });
        return distance
    };


    var totalDistance = getDistance(leg1.departingCity, leg1.arrivalCity, routes) 
        + getDistance(leg2.departingCity, leg2.arrivalCity, routes)
        + getDistance(leg3.departingCity, leg3.arrivalCity, routes)
        + getDistance(leg4.departingCity, leg4.arrivalCity, routes)

    document.getElementById("distanceresult").innerHTML = totalDistance;
}

非常感谢您的帮助,这与我的想法非常不同,非常有帮助。我可以看到您在 fiddle 上的代码完美运行,但出于某种原因,当我在浏览器上尝试时它不起作用。也许与 lodash 函数的使用有关?(在看到您的回复之前,我从未听说过 lodash..) - Mike1986
@Mike1986 lodash是一个非常棒的库,可以进行一些非常酷的数据操作。它非常轻量级!你只需要在HTML文件底部添加一个脚本标签,像这样: <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script> - spoonscen
谢谢,我现在正在研究这个,非常有帮助! - Mike1986

2
这是我处理这个问题的方法。
首先,构建一个包含每个距离的数据结构。为此,我做出了以下假设:
1. 无论数据集中可能存在哪些机场,从机场1到机场2的距离始终与从机场2到机场1的距离相同。 2. 数据集中任何机场到任何其他机场的距离都可以定义为单个常数。
在JavaScript中,可以像这样表示该数据结构(虽然最好将其存储为JSON对象):
var routes = {

    BCN: {

        MAD: 483

    },

    JFK: {

        MAD: 5761,
        BCN: 6150

    },

    LHR: {

        MAD: 1244,
        BCN: 1148,
        JFK: 5539

    },

    ORD: {

        MAD: 6744,
        BCN: 7093,
        JFK: 1188,
        LHR: 6343

    }
};

请注意,每个属性都引用其上面的属性和根情况“MAD”,但不包括下面的属性。这消除了必须两次存储每个值的冗余。它还使得添加更多数据变得更加简单,您只需要为每个后续机场添加定义和距离,而无需修改之前的数据。
现在,您只需要一个函数来读取该数据结构。这个基本的函数似乎非常适合:
function getDistance (airport1, airport2) {

    if (routes [airport1] && routes [airport1][airport2])
        return routes [airport1][airport2];

    if (routes [airport2] && routes [airport2][airport1])
        return routes [airport2][airport1];

    return null;

}

根据您的需求,您可能需要自定义回退情况的return null;,但除此之外,这应该符合您的需求。


非常感谢您的帮助。我也会研究一下 JSON 对象的替代方案,其他人也推荐过。谢谢。 - Mike1986

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接