简体   繁体   English

如果我的应用中有其他条件语句,我该如何重构这些javascript?

[英]How do I refactor these javascript if else conditional statements in my app?

I am building a calculator that uses two sliders like this: 我正在构建一个使用两个滑块的计算器,如下所示:

在此处输入图片说明

I have a range of CPU and RAM data that is stored in an object like this: 我有一系列存储在这样的对象中的CPU和RAM数据:

var CloudPlans = {
   small: {

        id: 'small',

        from: {
            cpu: 1,
            ram: 1
        },

        to: {
            cpu: 2,
            ram: 2
        },

        price: {
            linux: 3490,
            windows: 4190
        }
    },

    medium:  {

        id: 'medium',

        from: {
            cpu: 2,
            ram: 2
        },

        to: {
            cpu: 4,
            ram: 4
        },

        price: {
            linux: 5600,
            windows: 6300
        }

    },

    large: {

        id: 'large',

        from: {
            cpu: 4,
            ram: 4
        },

        to: {
            cpu: 6,
            ram: 8
        },

        price: {
            linux: 9500,
            windows: 10200
        }

    },

           [...more configs here]

}

Now based on the position and value of the slider, I have to check which plan the user has selected and then calculate the price of the components. 现在,根据滑块的位置和值,我必须检查用户选择的计划,然后计算组件的价格。 Here is the function that checks the price range: 这是检查价格范围的函数:

    checkPlaninRange: function(cpuVal, ramVal) {
        if(cpuVal >= CloudPlan.small.from.cpu && cpuVal <= CloudPlan.small.to.cpu ) {
            return "small";
        } else if (ramVal >= CloudPlan.small.from.cpu && ramVal <= CloudPlan.small.to.cpu) {
            return "small";
        }
    }

As you can see I will be dealing with almost an endless list of conditionals to return the selected plan. 如您所见,我将处理几乎无穷无尽的条件列表,以返回所选计划。 Is there any way to simplify the storage or selection of these plan configs based on code other than conditionals or case statements? 除了条件语句或案例语句之外,是否有任何方法可以简化基于代码的这些计划配置的存储或选择?

Use an array instead: 改用数组:

var CloudPlans = [
   {
        id: 'small',
        from: {
            cpu: 1,
            ram: 1
        },
        to: {
            cpu: 2,
            ram: 2
        },
        price: {
            linux: 3490,
            windows: 4190
        }
    },

    {
        id: 'medium',
        from: {
            cpu: 2,
            ram: 2
        },
        to: {
            cpu: 4,
            ram: 4
        },
        price: {
            linux: 5600,
            windows: 6300
        }
    },
    {
        id: 'large',
        from: {
            cpu: 4,
            ram: 4
        },
        to: {
            cpu: 6,
            ram: 8
        },
        price: {
            linux: 9500,
            windows: 10200
        }
    },
           //[...more configs here]
}

Now you can simply iterate over CloudPlans : 现在,您可以简单地遍历CloudPlans

for(int planIdx = 0; planIdx < CloudPlans.length; ++planIdx) {
    var plan = CloudPlan[planIdx];
    if(cpuVal >= plan.from.cpu && cpuVal <= plan.to.cpu  || 
       ramVal >= plan.from.ram && ramVal <= plan.to.ram) {
           return plan.id;
    }
}

Well, coming back to this question, I thought I'd throw in my two cents... 好了,回到这个问题,我以为我会花两分钱...

I would compress your data storage a bit by using an Array so there's no more need for the min values. 我会使用数组来压缩您的数据存储,因此不再需要min

var CloudPlans = [
   {    id: 'small',
        maxcpu: 2,
        maxram: 2,
        price: {
            linux: 3490,
            windows: 4190
        }
    }, {id: 'medium',
        maxcpu: 4,
        maxram: 4,
        price: {
            linux: 5600,
            windows: 6300
        }
    }, {id: 'large',
        maxcpu: 6,
        maxram: 8,
        price: {
            linux: 9500,
            windows: 10200
        }
    }, 
    // etc
].reverse(); // reverse it so the highest plan is first

Notice the .reverse() . 注意.reverse() We're going to compare from the highest down. 我们将从最高点开始进行比较。


Then use a reduce function: 然后使用reduce函数:

checkPlaninRange: function(cpuVal, ramVal) {
    return CloudPlans.reduce(function(plan, compare) {
        return cpuVal <= compare.maxcpu && 
               ramVal <= compare.maxram    ? compare : plan;
    }).id; // remove .id to return the entire object
}

Or if you want something a little more efficient, use a for loop in the same way: 或者,如果您想要更有效的方法,请以相同的方式使用for循环:

checkPlaninRange: function(cpuVal, ramVal) {
    var plan = CloudPlans[0];
    for (var i = 1; i < CloudPlans.length; i++) {
        if (cpuVal <= CloudPlans[i].maxcpu && 
            ramVal <= CloudPlans[i].maxram    ) {
            plan = CloudPlans[i];
        } else break;
    }
    return plan.id; // remove .id to return the entire object
}

Not quite as clean, but it lets you break the loop early. 不太干净,但是它可以让您尽早打破循环。


These are easy to extend with additional similar comparisons. 这些很容易通过其他类似的比较进行扩展。

You can loop over the config with the given vals. 您可以使用给定的val遍历配置。 Something like 就像是

var planFrom, planTo, cpuInRange, ramInRange;

for (var plan in CloudPlans) {
   planFrom = plan.from;
   planTo = plan.to;
   cpuInRange = cpuVal >= planFrom.cpu && cpuVal < planTo.cpu;  
   ramInRange = ramVal >= plamFrom.ram...; 
   if (cpuInRange || ramInRange) {
      return plan.id; 
   } 
}

You can make a more general function from this: 您可以从中执行更通用的功能:

function check(plan, values) {
    for (var prop in values)
        if (plan.from[prop] <= values[prop] && plan.to[prop] >= values[prop])
             return true; // if only one property is met
    return false;
}
// yet I guess this is what you want:
function check(plan, values) {
    for (var prop in values)
        if (plan.from[prop] > values[prop] || plan.to[prop] < values[prop])
             return false; // if only one property is not met
    return true; // if all properties are met
}

Now your checkPlaninRange method could look like that: 现在,您的checkPlaninRange方法可能如下所示:

checkSmallRange: function(cpuVal, ramVal) {
    if ( check(CloudPlan.small, {cpu:cpuVal, ram:ramVal}) )
        return "small";
}

Of course you also can loop your cloud plans with that: 当然,您还可以使用以下方法循环执行云计划:

getPossiblePlans: function(cpuVal, ramVal) {
    var plans = []
    for (var id in CloudPlans)
        if ( check(CloudPlans[id], {cpu:cpuVal, ram:ramVal}) )
            plans.push(id);
    return plans;
}

As @Tomasz Nurkiewicz mentioned, an array with a defined loop order would be better here. 就像@Tomasz Nurkiewicz提到的那样,这里定义循环顺序的数组会更好。 With CloudPlans being an object, the enumeration order is undefined (implementation-dependent) so it might return any plan when their ranges are not distinct. CloudPlans为对象,枚举顺序是不确定的(取决于实现),因此当它们的范围不明确时,它可能会返回任何计划。

One simple thing you could do is (dynamically, up front) create arrays whose values represent the respective ranges: 您可以做的一件事是(动态地,预先地)创建其值代表相应范围的数组:

var cpu = ["small", "small", "medium", "medium", "medium", "large"];
var ram = ["small", "medium", "medium", "medium", "large"];

Which you'd use like this: 您将这样使用:

function checkPlaninRange(cpuVal, ramVal) {
    return cpu[Math.floor(cpuVal)] || "large";
}

checkPlaninRange(4.2); // "medium"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM