繁体   English   中英

我应该如何处理嵌套条件语句?

[英]How should I deal with nested conditional statements?

我进行了一系列嵌套的条件检查,并尝试提出一个干净的解决方案,并尽可能避免if{}else{}地狱。 请参阅示例代码以说明我要实现的目标。

总而言之,我有两个对象CACHE_FILE_AGE_LIMITCACHE_FILE_CURRENT_AGE并且我正在尝试进行嵌套的年龄检查:

first check the days,
    then check hours,
       then check minutes,
           then check seconds

这个想法是,当我们达到一个较大的值(例如天数相等)的那一刻,我们继续使用小时,如果在此获得了较大的小时值,我们将结束检查。

请参阅示例以获取更多信息。

 const CACHE_FILE_AGE_LIMIT = { days: 3, hours: 6, minutes: 15, seconds: 57 } const CACHE_FILE_CURRENT_AGE = { days: 3, hours: 5, minutes: 14, seconds: 57 } function timeDiff(ageObj1, ageObj2) { console.log('days_limit', ageObj1.days, '?', 'days_age', ageObj2.days); // old: days document.getElementById("current_days").innerHTML = ageObj2.days; if (ageObj1.days < ageObj2.days) { console.log('old (days)'); document.getElementById("current_days").classList.add("red"); return true; } else { // equal: days if (ageObj1.days == ageObj2.days) { document.getElementById("current_hours").innerHTML = ageObj2.hours; console.log('\\tnext: hours'); console.log('\\thours_limit', ageObj1.hours, '?', 'hours_age', ageObj2.hours); if (ageObj1.hours < ageObj2.hours) { console.log('\\told (hours)'); document.getElementById("current_hours").classList.add("red"); return true; } else { // equal: hours if (ageObj1.hours == ageObj2.hours) { document.getElementById("current_minutes").innerHTML = ageObj2.minutes; console.log('\\t\\tnext (minutes)'); console.log('\\t\\tminutes_limit', ageObj1.minutes, '?', 'minutes_age', ageObj2.minutes); if (ageObj1.minutes < ageObj2.minutes) { // old: minutes console.log('\\t\\told (minutes)'); document.getElementById("current_minutes").classList.add("red"); return true; } else { // equal: minutes if (ageObj1.minutes == ageObj2.minutes) { document.getElementById("current_seconds").innerHTML = ageObj2.seconds; console.log('\\t\\t\\tnext (seconds)'); console.log('\\t\\t\\tseconds_limit', ageObj1.seconds, '?', 'seconds_age', ageObj2.seconds); if (ageObj1.seconds < ageObj2.seconds) { console.log('\\t\\t\\told (seconds)'); document.getElementById("current_seconds").classList.add("red"); return true; } else { console.log('\\t\\t\\tNOT old (seconds)'); document.getElementById("current_seconds").classList.add("blue"); return false; } } else { console.log('\\t\\tNOT old (minutes)'); return false; } } } else { console.log('\\tNOT old (hours)'); document.getElementById("current_hours").classList.add("blue"); return false; } } } else { console.log('NOT old (days)'); document.getElementById("current_days").classList.add("blue"); return false; } } } // Populate Limits var limit_fields = document.querySelectorAll(".limit"); for(i=0; i < limit_fields.length; i++){ //console.log('--->', i) let id = limit_fields[i].id.split("_")[1]; let val = CACHE_FILE_AGE_LIMIT[id] //console.log('\\tid:', id, 'val:', val); limit_fields[i].innerHTML = val; } // Evaluate Age document.getElementById("output").innerHTML = timeDiff(CACHE_FILE_AGE_LIMIT, CACHE_FILE_CURRENT_AGE) ? "old" : "up to date"; 
 .tg { border-collapse: collapse; border-spacing: 0; } .tg td { font-family: Arial, sans-serif; font-size: 12px; padding: 10px 5px; border-style: solid; border-width: 1px; overflow: hidden; word-break: normal; border-color: black; } .tg th { font-family: Arial, sans-serif; font-size: 12px; font-weight: normal; padding: 10px 5px; border-style: solid; border-width: 2px; overflow: hidden; border-color: black; } .tg .value { color: blue; text-align: center; vertical-align: top; } .tg .current { color: blue; text-align: center; vertical-align: top; } .tg .current.red { color: red; } .tg .current.blue { color: blue; } .tg .limit { color: #85929E; text-align: center; vertical-align: top; } .tg .header { background-color: #ffffc7; text-align: center; vertical-align: top; } .tg .item { background-color: #ffffc7; font-style: italic; text-align: right; vertical-align: top; } .tg .empty { background-color: #9b9b9b; text-align: right; vertical-align: top; } .tg .result { font-weight: bold; font-style: italic; background-color: #ffce93; text-align: right; vertical-align: top; } .tg .output { background-color: #FDEBD0; text-align: center; vertical-align: top; } 
 <table class="tg" style="undefined;table-layout: fixed; width: 265px"> <colgroup> <col style="width: 92px"> <col style="width: 92px"> <col style="width: 92px"> </colgroup> <tr> <th class="empty"></th> <th class="header">CURRENT</th> <th class="header">LIMITS</th> </tr> <tr> <td class="item">DAYS</td> <td id="current_days" class="value current">-</td> <td id="limit_days" class="value limit"></td> </tr> <tr> <td class="item">HOURS</td> <td id="current_hours" class="value current">-</td> <td id="limit_hours" class="value limit"></td> </tr> <tr> <td class="item">MINUTES</td> <td id="current_minutes" class="value current">-</td> <td id="limit_minutes" class="value limit"></td> </tr> <tr> <td class="item">SECONDS</td> <td id="current_seconds" class="value current">-</td> <td id="limit_seconds" class="value limit"></td> </tr> <tr> <td class="result">RESULT</td> <td id="output" class="output" colspan="2">up to date</td> </tr> </table> 

如您所见,一旦很明显hours足以确定年龄,则有条件执行结束。

请更改CACHE_FILE_CURRENT_AGE的值以CACHE_FILE_CURRENT_AGE进行测试。

-更新-

有多种解决方案,因此感谢大家的帮助。 不幸的是,我将不得不选择答案之一来结束问题。

这是解决方案的演示:

在此处输入图片说明

因此,另一种可能性是创建类似UNITS数组的对象,该数组仅包含您时事对象的每个属性的文本表示形式(按您要处理它们的顺序)。 然后,只需使用while循环来迭代该UNITS数组,然后依次更新每个DOM元素。

 const CACHE_FILE_AGE_LIMIT = { days: 3, hours: 6, minutes: 15, seconds: 57 }, CACHE_FILE_CURRENT_AGE = { days: 3, hours: 5, minutes: 17, seconds: 57 }, UNITS = ["days", "hours","minutes","seconds"] function timeDiff(ageObj1, ageObj2) { // We create a flag, and an index to iterate over our UNITS array let unitsIndex = 0; // if the upToDate flag is TRUE while(unitsIndex <= UNITS.length){ // We'll use template literals to create the IDs currentEl = document.getElementById(`current_${UNITS[unitsIndex]}`), limitEl = document.getElementById(`limit_${UNITS[unitsIndex]}`); console.log(UNITS[unitsIndex],ageObj1[UNITS[unitsIndex]],ageObj2[UNITS[unitsIndex]]) // Update the content of the current and limit elements currentEl.innerHTML = ageObj2[UNITS[unitsIndex]]; limitEl.innerHTML = ageObj1[UNITS[unitsIndex]]; // Here we check: is our limit unit less than our current? if (ageObj1[UNITS[unitsIndex]] < ageObj2[UNITS[unitsIndex]]) { /** * In this case, our current has exceeded our limit. Bad bad bad. **/ console.info(`The current ${UNITS[unitsIndex]} is stale.`) currentEl.classList.add("red"); return false; } else if(ageObj1[UNITS[unitsIndex]] > ageObj2[UNITS[unitsIndex]]){ /** * In this case, our limit is more than a full unit greater than our current. goodgoodgood. **/ console.info(`The current ${UNITS[unitsIndex]} is more than a full unit to the good.`) return true; } //increment our UNITS array pointer unitsIndex++; } // if we get here, then all the DHMS have passed -- we can return true return true; } // Populate Limits var limit_fields = document.querySelectorAll(".limit"); for(i=0; i < limit_fields.length; i++){ //console.log('--->', i) let id = limit_fields[i].id.split("_")[1]; let val = CACHE_FILE_AGE_LIMIT[id] //console.log('\\tid:', id, 'val:', val); limit_fields[i].innerHTML = val; } // Evaluate Age document.getElementById("output").innerHTML = timeDiff(CACHE_FILE_AGE_LIMIT, CACHE_FILE_CURRENT_AGE) ? "up to date" : "old"; 
 .tg { border-collapse: collapse; border-spacing: 0; } .tg td { font-family: Arial, sans-serif; font-size: 12px; padding: 10px 5px; border-style: solid; border-width: 1px; overflow: hidden; word-break: normal; border-color: black; } .tg th { font-family: Arial, sans-serif; font-size: 12px; font-weight: normal; padding: 10px 5px; border-style: solid; border-width: 2px; overflow: hidden; border-color: black; } .tg .value { color: blue; text-align: center; vertical-align: top; } .tg .current { color: blue; text-align: center; vertical-align: top; } .tg .current.red { color: red; } .tg .current.blue { color: blue; } .tg .limit { color: #85929E; text-align: center; vertical-align: top; } .tg .header { background-color: #ffffc7; text-align: center; vertical-align: top; } .tg .item { background-color: #ffffc7; font-style: italic; text-align: right; vertical-align: top; } .tg .empty { background-color: #9b9b9b; text-align: right; vertical-align: top; } .tg .result { font-weight: bold; font-style: italic; background-color: #ffce93; text-align: right; vertical-align: top; } .tg .output { background-color: #FDEBD0; text-align: center; vertical-align: top; } 
 <table class="tg" style="undefined;table-layout: fixed; width: 265px"> <colgroup> <col style="width: 92px"> <col style="width: 92px"> <col style="width: 92px"> </colgroup> <tr> <th class="empty"></th> <th class="header">CURRENT</th> <th class="header">LIMITS</th> </tr> <tr> <td class="item">DAYS</td> <td id="current_days" class="value current">-</td> <td id="limit_days" class="value limit"></td> </tr> <tr> <td class="item">HOURS</td> <td id="current_hours" class="value current">-</td> <td id="limit_hours" class="value limit"></td> </tr> <tr> <td class="item">MINUTES</td> <td id="current_minutes" class="value current">-</td> <td id="limit_minutes" class="value limit"></td> </tr> <tr> <td class="item">SECONDS</td> <td id="current_seconds" class="value current">-</td> <td id="limit_seconds" class="value limit"></td> </tr> <tr> <td class="result">RESULT</td> <td id="output" class="output" colspan="2">up to date</td> </tr> </table> 

请注意,我使用模板文字来定义每次迭代的id:

`current_${UNITS[unitIndex] }`

By doing so, I don't have to hard-code the id every time. As long as I can trust the prefixes, this works pretty well. And it seems to get rid of a lot of your if statements, simply by running them each sequentially.

EDIT: I'm an idiot. So there are two branches to your if statement (well, three). First, if the current is beyond the limit, return false immediately, as that is OLD. Second, if the limit is more than a full unit greater than the current, immediately return true, as the current is well within its limit. Third, if they are equal, loop on to the next unit. If all units process and we fall through the while loop, then  they are the same exact. Weird, but still good. Code updated to reflect the SECOND case.

将嵌套条件转换为代码的线性表示的唯一方法是将单个条件的微粒移动到函数中,并使用some短路导致退出运行。 当您需要返回一个值时,您需要存储此标志,因为some返回值对此不起作用。

这种方法的优点是添加或多或少的无限条件,根据需要打破它们,并返回布尔值以进行进一步的操作。

缺点是,您需要查找数据,嵌套结构和理解,即调用下一个条件/函数,直到该函数返回true为止,而不管标志的值如何。

 const CACHE_FILE_AGE_LIMIT = { days: 3, hours: 6, minutes: 15, seconds: 57 } const CACHE_FILE_CURRENT_AGE = { days: 3, hours: 5, minutes: 14, seconds: 57 } function timeDiff(ageObj1, ageObj2) { var flag; [ () => { document.getElementById("current_days").innerHTML = ageObj2.days; if (ageObj1.days < ageObj2.days) { document.getElementById("current_days").classList.add("red"); return flag = true; } }, () => { if (ageObj1.days == ageObj2.days) { document.getElementById("current_hours").innerHTML = ageObj2.hours; } else { document.getElementById("current_days").classList.add("blue"); flag = false; return true; } }, () => { if (ageObj1.hours < ageObj2.hours) { document.getElementById("current_hours").classList.add("red"); return flag = true; } }, () => { if (ageObj1.hours == ageObj2.hours) { document.getElementById("current_minutes").innerHTML = ageObj2.minutes; } else { document.getElementById("current_hours").classList.add("blue"); flag = false; return true; } }, () => { if (ageObj1.minutes < ageObj2.minutes) { document.getElementById("current_minutes").classList.add("red"); return flag = true; } }, () => { if (ageObj1.minutes == ageObj2.minutes) { document.getElementById("current_seconds").innerHTML = ageObj2.seconds; } else { flag = false; return true; } }, () => { if (ageObj1.seconds < ageObj2.seconds) { document.getElementById("current_seconds").classList.add("red"); return flag = true; } else { document.getElementById("current_seconds").classList.add("blue"); flag = false; return true; } } ].some(fn => fn()); return flag; } // Populate Limits var limit_fields = document.querySelectorAll(".limit"); for(i=0; i < limit_fields.length; i++){ //console.log('--->', i) let id = limit_fields[i].id.split("_")[1]; let val = CACHE_FILE_AGE_LIMIT[id] //console.log('\\tid:', id, 'val:', val); limit_fields[i].innerHTML = val; } // Evaluate Age document.getElementById("output").innerHTML = timeDiff(CACHE_FILE_AGE_LIMIT, CACHE_FILE_CURRENT_AGE) ? "old" : "up to date"; 
 .tg { border-collapse: collapse; border-spacing: 0; } .tg td { font-family: Arial, sans-serif; font-size: 12px; padding: 10px 5px; border-style: solid; border-width: 1px; overflow: hidden; word-break: normal; border-color: black; } .tg th { font-family: Arial, sans-serif; font-size: 12px; font-weight: normal; padding: 10px 5px; border-style: solid; border-width: 2px; overflow: hidden; border-color: black; } .tg .value { color: blue; text-align: center; vertical-align: top; } .tg .current { color: blue; text-align: center; vertical-align: top; } .tg .current.red { color: red; } .tg .current.blue { color: blue; } .tg .limit { color: #85929E; text-align: center; vertical-align: top; } .tg .header { background-color: #ffffc7; text-align: center; vertical-align: top; } .tg .item { background-color: #ffffc7; font-style: italic; text-align: right; vertical-align: top; } .tg .empty { background-color: #9b9b9b; text-align: right; vertical-align: top; } .tg .result { font-weight: bold; font-style: italic; background-color: #ffce93; text-align: right; vertical-align: top; } .tg .output { background-color: #FDEBD0; text-align: center; vertical-align: top; } 
 <table class="tg" style="undefined;table-layout: fixed; width: 265px"> <colgroup> <col style="width: 92px"> <col style="width: 92px"> <col style="width: 92px"> </colgroup> <tr> <th class="empty"></th> <th class="header">CURRENT</th> <th class="header">LIMITS</th> </tr> <tr> <td class="item">DAYS</td> <td id="current_days" class="value current">-</td> <td id="limit_days" class="value limit"></td> </tr> <tr> <td class="item">HOURS</td> <td id="current_hours" class="value current">-</td> <td id="limit_hours" class="value limit"></td> </tr> <tr> <td class="item">MINUTES</td> <td id="current_minutes" class="value current">-</td> <td id="limit_minutes" class="value limit"></td> </tr> <tr> <td class="item">SECONDS</td> <td id="current_seconds" class="value current">-</td> <td id="limit_seconds" class="value limit"></td> </tr> <tr> <td class="result">RESULT</td> <td id="output" class="output" colspan="2">up to date</td> </tr> </table> 

但是您可以使用带有键的数组并执行直到某些部分返回true

function timeDiff(ageObj1, ageObj2) {
    var flag;

    ['days', 'hours', 'minutes', 'seconds'].some((key, index, keys) => {
        var nextKey = keys[index + 1],
            element = document.getElementById("current_" + key),
            nextElement = document.getElementById("current_" + nextKey);

        element.innerHTML = ageObj2[key];
        if (ageObj1[key] < ageObj2[key]) {
            element.classList.add("red");
            return flag = true;
        }
        if (ageObj1[key] == ageObj2[key] && nextKey) {
            nextElement.innerHTML = ageObj2[nextKey];
        } else {
            element.classList.add("blue");
            flag = false;
            return true;
        }
    });

    return flag;
}

暂无
暂无

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

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