如何找出多个嵌套的 if else 条件?

How figure out multiple nested if else condition?

我没有找到一种有效的方法来检查下面提到的情况。 我想要实现的是—— 有一些进程需要完成,如果它们对应的布尔值是真的建议启动进程。所以我想检查一个特定的条件是否只有在它应该开始的时候才完成。

有一些布尔变量

var shouldStartProcessA
var shouldStartProcessB
var shouldStartProcessC

var isADone
var isBDone
var isCDone

if (shouldStartProcessA && shouldStartProcessB && shouldStartC) {
    if (isADone && isBDone && isCDone) {
        // Every process completed
    }
}

if (shouldStartProcessA && shouldStartProcessB) {
    if (isADone && isBDone) {
        // Every process completed
    }
}

if (shouldStartProcessA && shouldStartC) {
    if (isADone && isCDone) {
        // Every process completed
    }
}

if (shouldStartProcessB && shouldStartC) {
    if (isBDone && isCDone) {
        // Every process completed
    }
}

if (shouldStartProcessA) {
    if (isADone) {
        // Every process completed
    }
}

if (shouldStartProcessB) {
    if (isBDone) {
        // Every process completed
    }
}

if (shouldStartProcessC) {
    if (isCDone) {
        // Every process completed
    }
}

这种类型的验证条件通过引入每隔一个布尔值呈指数级增长。我正在努力寻找一个简单的实现来检查这些条件。

我想,您应该创建两个布尔值列表,然后添加变量。

val list1 = listOf(shouldStartProcessA, shouldStartProcessB, shouldStartC)
val list2 = listOf(isADone, isBDone, isCDone)

然后遍历两个列表并检查相应位置的项目是否具有相同的值。

var n = 0
for (i in list1.indices) {
   if (list1[i] == list2[i]) {
       n++
   } else {
       n = 0
       break
   }
}

if (n > 0) {
    // Every process completed
}

与其以这种方式做事,我推荐一种允许您添加任务并检查其状态的数据结构。有很多方法可以做到这一点,但基本思想是您可以遍历所有项目并使用 all 之类的函数来确认它们都处于适当的状态。这样你就不必 hand-wire 把所有东西放在一起

您可以使用 Map 并向其中添加任务,最初将它们映射到 false 并在完成后将其设置为 true。或者创建一个 Set 并将您的任务添加到其中(我假设您最多需要一个),并在完成后删除它们/将它们移至“已完成”列表。那种想法。如果你愿意,你可以创建一个 enum class 来代表你的任务,这样每个任务都是它自己的实例(例如 Process.A,就像有一个专用的固定变量)并且你可以轻松地在你的逻辑中使用它们


如果你真的想要每个进程的变量,而不是数据结构,我仍然建议将每一对滚动到一个状态,像这样:

enum class State {
    UNUSED, PENDING, DONE
}

var processA = State.UNUSED
var processB = State.PENDING
// etc

// you can easily check them like this:

// create a list of all the variables you want to check - we're using references
// to the properties themselves (with the ::), not the current value!
val allProcesses = listOf(::processA, ::processB)

// now you have that collection, you can easily iterate over them all
// and work out what's what - we need to use get() to get the current values
val allFinished = allProcesses
    .filterNot { it.get() == State.UNUSED } // ignore unused processes
    .all { it.get() == State.DONE } // check ALL the required ones are DONE

你可以把那个检查写成一个 all 条件,但关键是要告诉你你可以灵活地使用它,并通过过滤掉你不感兴趣的东西来建立你的逻辑在,如果你创建一组有用的状态


如果您真的想(或必须)坚持当前的“变量对”设置,您可以做类似的事情:

// wiring them up again, creating a list of Pairs so we can iterate over them easily
val allProcesses = listOf(
    ::shouldStartProcessA to ::isADone,
    ::shouldStartProcessB to ::isBDone,
    ::shouldStartProcessC to ::isCDone
)

// gotta check 'em all - only returns true if that ALL meet the condition
val allComplete = allProcesses.all { (shouldStart, isDone) ->
    // the get() syntax is awkward, but basically for everything we're checking
    // if it either doesn't need to start, or it does but it's also done
    !shouldStart.get() || (shouldStart.get() && isDone.get())
}

所以添加新进程只是将它们的变量添加到对列表中的一种情况,它们会包含在检查中


如果您在检查之前创建列表,则不需要 属性 参考资料 (::/.get())它们,但是如果你想提前定义它们一次(并且 属性 值可以在那之后改变)那么你就是这样做的。否则你可以只做正常的 shouldStartProcessA to isADone 等,这对大多数情况来说可能没问题 - 我将参考资料作为处理此类事情的更一般的例子