I am not getting the efficient way to check below mentioned condition. What I want to achieve is that- There are some process need to be done if there corresponding boolean is true suggesting to start the process. So I want to check if particular condition is done and only check is it was started.
There are some boolean variables
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
}
}
This type of validating condition grows exponentially by introducing every other boolean. I am struggling to find a straightforward implementation to check these conditions.
CodePudding user response:
Instead of doing things this way, I'd recommend a data structure that allows you to add tasks and check their state. There are a lot of ways to do that, but the basic idea is you can iterate over all the items and use functions like all
to confirm they're all in the appropriate state. That way you don't have to hand-wire everything together
You could use a Map
and add tasks to it, initially mapping them to false
and setting that to true
when they're completed. Or create a Set
and add your tasks to that (I'm assuming you want one of each at most), and remove them / move them to a "done" list when they complete. That kind of idea. You could create an enum class
to represent your tasks if you want, so each one is its own instance (e.g. Process.A
, like having a dedicated, fixed variable) and you can easily use those in your logic
If you really want variables for each process, instead of a data structure, I'd still recommend rolling each pair into a single state, something like this:
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
You could write that check there as a single all
condition, but the point is to show you you can be flexible with it, and build up your logic by filtering out the stuff you're not interested in, if you create a useful set of states
If you really do want to (or have to) stick with the current "pairs of variables" setup, you can do something similar:
// 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())
}
so adding new processes is just a case of adding their variables to the list of pairs, and they get included in the checking
You don't need the property reference stuff (::
/.get()
) if you create the lists right before you check them, but if you want to define them once in advance (and the property values can change after that) then that's how you'd do it. Otherwise you can just do the normal shouldStartProcessA to isADone
etc, which is probably fine for most cases - I'm showing the reference stuff as a more general example for handling this kind of thing
CodePudding user response:
I suppose, you should create two lists of Boolean and add variables consequently.
val list1 = listOf(shouldStartProcessA, shouldStartProcessB, shouldStartC)
val list2 = listOf(isADone, isBDone, isCDone)
Then iterate over both lists and check that items in corresponding positions have the same values.
var n = 0
for (i in list1.indices) {
if (list1[i] == list2[i]) {
n
} else {
n = 0
break
}
}
if (n > 0) {
// Every process completed
}