How to code these conditional statements in more elegant & scalable manner
Clash Royale CLAN TAG#URR8PPP
In my software, I need to decide the version of a feature based on 2 parameters. Eg.
Render version 1 -> if (param1 && param2) == true;
Render version 2 -> if (!param1 && !param2) == true;
Render version 3 -> if only param1 == true;
Render version 4 -> if only param2 == true;
So, to meet this requirement, I wrote a code which looks like this -
if(param1 && param2) //both are true
version = 1;
else if(!param1 && !param2) //both are false
version = 2;
else if(!param2) //Means param1 is true
version = 3;
else //Means param2 is true
version = 4;
There are definitely multiple ways to code this but I finalised this approach after trying out different approaches because this is the most readable code I could come up with.
But this piece of code is definitely not scalable because -
- Let say tomorrow we want to introduce new param called param3. Then
the no. of checks will increase because of multiple possible
combinations. - For this software, I am pretty much sure that we
will have to accommodate new parameters in future.
Can there be any scalable & readable way to code these requirements?
java algorithm if-statement
|
show 3 more comments
In my software, I need to decide the version of a feature based on 2 parameters. Eg.
Render version 1 -> if (param1 && param2) == true;
Render version 2 -> if (!param1 && !param2) == true;
Render version 3 -> if only param1 == true;
Render version 4 -> if only param2 == true;
So, to meet this requirement, I wrote a code which looks like this -
if(param1 && param2) //both are true
version = 1;
else if(!param1 && !param2) //both are false
version = 2;
else if(!param2) //Means param1 is true
version = 3;
else //Means param2 is true
version = 4;
There are definitely multiple ways to code this but I finalised this approach after trying out different approaches because this is the most readable code I could come up with.
But this piece of code is definitely not scalable because -
- Let say tomorrow we want to introduce new param called param3. Then
the no. of checks will increase because of multiple possible
combinations. - For this software, I am pretty much sure that we
will have to accommodate new parameters in future.
Can there be any scalable & readable way to code these requirements?
java algorithm if-statement
Are yo usure that the if/else if cascade is correct ? Because if some test returns true, the next won't be evaluated at all.
– Yves Daoust
Feb 16 at 16:11
@YvesDaoust Seems correct, doesn't it? I think it is desired that only oneif
body is visited
– Lino
Feb 16 at 16:18
@Lino: mutual exclusiveness of the expressions must be guaranteed then.
– Yves Daoust
Feb 16 at 16:22
What is the expected result withparam3
? Can you describe the pattern change generally as we add params?
– גלעד ברקן
Feb 16 at 16:28
Do you plan to increase versions as well?
– Nitin
Feb 16 at 19:53
|
show 3 more comments
In my software, I need to decide the version of a feature based on 2 parameters. Eg.
Render version 1 -> if (param1 && param2) == true;
Render version 2 -> if (!param1 && !param2) == true;
Render version 3 -> if only param1 == true;
Render version 4 -> if only param2 == true;
So, to meet this requirement, I wrote a code which looks like this -
if(param1 && param2) //both are true
version = 1;
else if(!param1 && !param2) //both are false
version = 2;
else if(!param2) //Means param1 is true
version = 3;
else //Means param2 is true
version = 4;
There are definitely multiple ways to code this but I finalised this approach after trying out different approaches because this is the most readable code I could come up with.
But this piece of code is definitely not scalable because -
- Let say tomorrow we want to introduce new param called param3. Then
the no. of checks will increase because of multiple possible
combinations. - For this software, I am pretty much sure that we
will have to accommodate new parameters in future.
Can there be any scalable & readable way to code these requirements?
java algorithm if-statement
In my software, I need to decide the version of a feature based on 2 parameters. Eg.
Render version 1 -> if (param1 && param2) == true;
Render version 2 -> if (!param1 && !param2) == true;
Render version 3 -> if only param1 == true;
Render version 4 -> if only param2 == true;
So, to meet this requirement, I wrote a code which looks like this -
if(param1 && param2) //both are true
version = 1;
else if(!param1 && !param2) //both are false
version = 2;
else if(!param2) //Means param1 is true
version = 3;
else //Means param2 is true
version = 4;
There are definitely multiple ways to code this but I finalised this approach after trying out different approaches because this is the most readable code I could come up with.
But this piece of code is definitely not scalable because -
- Let say tomorrow we want to introduce new param called param3. Then
the no. of checks will increase because of multiple possible
combinations. - For this software, I am pretty much sure that we
will have to accommodate new parameters in future.
Can there be any scalable & readable way to code these requirements?
java algorithm if-statement
java algorithm if-statement
edited Feb 16 at 20:16
Alexis Wilke
10.1k34180
10.1k34180
asked Feb 16 at 13:08
Ryan GustoRyan Gusto
593
593
Are yo usure that the if/else if cascade is correct ? Because if some test returns true, the next won't be evaluated at all.
– Yves Daoust
Feb 16 at 16:11
@YvesDaoust Seems correct, doesn't it? I think it is desired that only oneif
body is visited
– Lino
Feb 16 at 16:18
@Lino: mutual exclusiveness of the expressions must be guaranteed then.
– Yves Daoust
Feb 16 at 16:22
What is the expected result withparam3
? Can you describe the pattern change generally as we add params?
– גלעד ברקן
Feb 16 at 16:28
Do you plan to increase versions as well?
– Nitin
Feb 16 at 19:53
|
show 3 more comments
Are yo usure that the if/else if cascade is correct ? Because if some test returns true, the next won't be evaluated at all.
– Yves Daoust
Feb 16 at 16:11
@YvesDaoust Seems correct, doesn't it? I think it is desired that only oneif
body is visited
– Lino
Feb 16 at 16:18
@Lino: mutual exclusiveness of the expressions must be guaranteed then.
– Yves Daoust
Feb 16 at 16:22
What is the expected result withparam3
? Can you describe the pattern change generally as we add params?
– גלעד ברקן
Feb 16 at 16:28
Do you plan to increase versions as well?
– Nitin
Feb 16 at 19:53
Are yo usure that the if/else if cascade is correct ? Because if some test returns true, the next won't be evaluated at all.
– Yves Daoust
Feb 16 at 16:11
Are yo usure that the if/else if cascade is correct ? Because if some test returns true, the next won't be evaluated at all.
– Yves Daoust
Feb 16 at 16:11
@YvesDaoust Seems correct, doesn't it? I think it is desired that only one
if
body is visited– Lino
Feb 16 at 16:18
@YvesDaoust Seems correct, doesn't it? I think it is desired that only one
if
body is visited– Lino
Feb 16 at 16:18
@Lino: mutual exclusiveness of the expressions must be guaranteed then.
– Yves Daoust
Feb 16 at 16:22
@Lino: mutual exclusiveness of the expressions must be guaranteed then.
– Yves Daoust
Feb 16 at 16:22
What is the expected result with
param3
? Can you describe the pattern change generally as we add params?– גלעד ברקן
Feb 16 at 16:28
What is the expected result with
param3
? Can you describe the pattern change generally as we add params?– גלעד ברקן
Feb 16 at 16:28
Do you plan to increase versions as well?
– Nitin
Feb 16 at 19:53
Do you plan to increase versions as well?
– Nitin
Feb 16 at 19:53
|
show 3 more comments
5 Answers
5
active
oldest
votes
EDIT:
For a scalable solution define the versions for each parameter combination through a Map
:
Map<List<Boolean>, Integer> paramsToVersion = Map.of(
List.of(true, true), 1,
List.of(false, false), 2,
List.of(true, false), 3,
List.of(false, true), 4);
Now finding the right version is a simple map lookup:
version = paramsToVersion.get(List.of(param1, param2));
The way I initialized the map works since Java 9. In older Java versions it’s a little more wordy, but probably still worth doing. Even in Java 9 you need to use Map.ofEntries
if you have 4 or more parameters (for 16 combinations), which is a little more wordy too.
Original answer:
My taste would be for nested if
/else
statements and only testing each parameter once:
if (param1)
if (param2)
version = 1;
else
version = 3;
else
if (param2)
version = 4;
else
version = 2;
But it scales poorly to many parameters.
I don't like the new solution because you will have to generate up to 2^k lists for k parameters. This is unreadable, and the expansion of the lists is error prone.
– Yves Daoust
Feb 16 at 16:36
@YvesDaoust Then I’m glad that I let my old solution stand here too. I suppose each has its place depending on requirements and circumstances. At least if you add 2^k lists and get a param value wrong, in Java 9Map.of
orMap.ofEntries
will complain about the resulting duplicate kay so you know there’s an error and you need to fix it.
– Ole V.V.
Feb 16 at 16:41
1
This kind of error can be spotted at a glance as the values appear explicitly. What I am referring to is how you expand "(tall and not fat) or old and green" without a mistake, and how you can read that back from the truth table.
– Yves Daoust
Feb 16 at 16:43
@Ole V.V. Yes these are better solutions than mine but scalability concern is still there.
– Ryan Gusto
Feb 17 at 2:34
add a comment |
If you have to enumerate all the possible combinations of Booleans, it's often simplest to convert them into a number:
// param1: F T F T
// param2; F F T T
static final int VERSIONS = new int2, 3, 4, 1;
...
version = VERSIONS[(param1 ? 1:0) + (param2 ? 2:0)];
@Lino: that won't work,i
will always stay0
, no matter how often you shift it left.
– Ralf Kleberhoff
Feb 16 at 14:12
7
This is really clever, but far from being readable and expressive. For a developer that is new to this code, it might even result cryptic.
– Federico Peralta Schaffner
Feb 16 at 16:32
@FedericoPeraltaSchaffner agreed, but there are readable variants and/or ways to comment it. I'm just leaving that to the OP, since I would like a more concrete example before suggesting a best way.
– Matt Timmermans
Feb 16 at 17:56
I think the answer would benefit from including a comment or an example showing how to extend this beyond two parameters; e.g.(param3 ? 4:0) + (param4 ? 8:0) + ...
, as it may not be clear to some that you are treating the bool sequence as a bit string.
– Filip Milovanović
Feb 16 at 18:29
I'm not sure this passes either the scalable or readable stated requirements. Ok, it might be technically scalable but as we'd add to the list of ternaryif
s, the expression evaluating the index will very quickly get unreadable (to me it already is, which doesn't say much about me I guess :)
– גלעד ברקן
Feb 17 at 12:02
add a comment |
I doubt that there is a way that would be more compact, readable and scalable at the same time.
You express the conditions as minimized expressions, which are compact and may have meaning (in particular, the irrelevant variables don't clutter them). But there is no systematism that you could exploit.
A quite systematic alternative could be truth tables, i.e. the explicit expansion of all combinations and the associated truth value (or version number), which can be very efficient in terms of running-time. But these have a size exponential in the number of variables and are not especially readable.
I am afraid there is no free lunch. Your current solution is excellent.
If you are after efficiency (i.e. avoiding the need to evaluate all expressions sequentially), then you can think of the truth table approach, but in the following way:
declare an array of version numbers, with 2^n entries;
use the code just like you wrote to initialize all table entries; to achieve that, enumerate all integers in [0, 2^n) and use their binary representation;
now for a query, form an integer index from the n input booleans and lookup the array.
Using the answer by Olevv, the table would be [2, 4, 3, 1]. A lookup would be like (false, true) => T[01b] = 4.
What matters is that the original set of expressions is still there in the code, for human reading. You can use it in an initialization function that will fill the array at run-time, and you can also use it to hard-code the table (and leave the code in comments; even better, leave the code that generates the hard-coded table).
add a comment |
Your combinations of parameters is nothing more than a binary number (like 01100
) where the 0
indicates a false
and the 1
a true
.
So your version can be easily calculated by using all the combinations of ones and zeroes. Possible combinations with 2 input parameters are:
11
-> both aretrue
10
-> first istrue
, second isfalse
01
-> first isfalse
, second istrue
00
-> both arefalse
So with this knowledge I've come up with a quite scalable solution using a "bit mask" (nothing more than a number) and "bit operations":
public static int getVersion(boolean... params)
int length = params.length;
int mask = (1 << length) - 1;
for(int i = 0; i < length; i++)
if(!params[i])
mask &= ~(1 << length - i - 1);
return mask + 1;
The most interesting line is probably this:
mask &= ~(1 << length - i - 1);
It does many things at once, I split it up. The part length - i - 1
calculates the position of the "bit" inside the bit mask from the right (0
based, like in arrays).
The next part: 1 << (length - i - 1)
shifts the number 1
the amount of positions to the left. So lets say we have a position of 3, then the result of the operation 1 << 2
(2
is the third position) would be a binary number of the value 100
.
The ~
sign is a binary inverse, so all the bits are inverted, all 0
are turned to 1
and all 1
are turned to 0
. With the previous example the inverse of 100
would be 011
.
The last part: mask &= n
is the same as mask = mask & n
where n
is the previously computed value 011
. This is nothing more than a binary AND, so all the same bits which are in mask
and in n
are kept, where as all others are discarded.
All in all, does this single line nothing more than remove the "bit" at a given position of the mask
if the input parameter is false
.
If the version numbers are not sequential from 1
to 4
then a version lookup table, like this one may help you.
The whole code would need just a single adjustment in the last line:
return VERSIONS[mask];
Where your VERSIONS
array consists of all the versions in order, but reversed. (index 0
of VERSIONS
is where both parameters are false)
2
I don't really care about downvotes, but may the downvoter mention why? So I could improve the answer if needed
– Lino
Feb 16 at 17:27
2
Very solid approach.
– user58697
Feb 16 at 17:46
I didn't downvote this, but this does look a bit convoluted so I wouldn't be surprised that someone thought it downvote-worthy. Part of it might be the negative logic; it might feel more natural to just set the value to zero to start with, and then set the bits as necessary. Also, I think you could make the(1 << length - i - 1)
clearer by running the loop downwards, not up and then just have(1 << i)
.
– ilkkachu
Feb 16 at 22:52
Even more so, doesint mask = length * 2 - 1;
work? If there are three items in the list, this givesmask = 5
, and 5 is0101
and I'm not sure how that's useful?
– ilkkachu
Feb 16 at 22:54
How is this readable (a stated requirement by the OP)? "Readable" to me would mean being able to easily follow how the set of params, and each individual one, contributes to the expression evaluating the version. I can't find a place like that in the code snippet. (I did not downvote.)
– גלעד ברקן
Feb 17 at 15:23
add a comment |
I would have just gone with:
if (param1)
if (param2)
else
else
if (param2)
else
Kind of repetitive, but each condition is evaluated only once, and you can easily find the code that executes for any particular combination. Adding a 3rd parameter will, of course, double the code. But if there are any invalid combinations, you can leave those out which shortens the code. Or, if you want to throw an exception for them, it becomes fairly easy to see which combination you have missed. When the IF's become too long, you can bring the actual code out in methods:
if (param1)
if (param2)
method_12();
else
method_1();
else
if (param2)
method_2();
else
method_none();
Thus your whole switching logic takes up a function of itself and the actual code for any combination is in another method. When you need to work with the code for a particular combination, you just look up the appropriate method. The big IF maze is then rarely looked at, and when it is, it contains only the IFs themselves and nothing else potentially distracting.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54723382%2fhow-to-code-these-conditional-statements-in-more-elegant-scalable-manner%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
EDIT:
For a scalable solution define the versions for each parameter combination through a Map
:
Map<List<Boolean>, Integer> paramsToVersion = Map.of(
List.of(true, true), 1,
List.of(false, false), 2,
List.of(true, false), 3,
List.of(false, true), 4);
Now finding the right version is a simple map lookup:
version = paramsToVersion.get(List.of(param1, param2));
The way I initialized the map works since Java 9. In older Java versions it’s a little more wordy, but probably still worth doing. Even in Java 9 you need to use Map.ofEntries
if you have 4 or more parameters (for 16 combinations), which is a little more wordy too.
Original answer:
My taste would be for nested if
/else
statements and only testing each parameter once:
if (param1)
if (param2)
version = 1;
else
version = 3;
else
if (param2)
version = 4;
else
version = 2;
But it scales poorly to many parameters.
I don't like the new solution because you will have to generate up to 2^k lists for k parameters. This is unreadable, and the expansion of the lists is error prone.
– Yves Daoust
Feb 16 at 16:36
@YvesDaoust Then I’m glad that I let my old solution stand here too. I suppose each has its place depending on requirements and circumstances. At least if you add 2^k lists and get a param value wrong, in Java 9Map.of
orMap.ofEntries
will complain about the resulting duplicate kay so you know there’s an error and you need to fix it.
– Ole V.V.
Feb 16 at 16:41
1
This kind of error can be spotted at a glance as the values appear explicitly. What I am referring to is how you expand "(tall and not fat) or old and green" without a mistake, and how you can read that back from the truth table.
– Yves Daoust
Feb 16 at 16:43
@Ole V.V. Yes these are better solutions than mine but scalability concern is still there.
– Ryan Gusto
Feb 17 at 2:34
add a comment |
EDIT:
For a scalable solution define the versions for each parameter combination through a Map
:
Map<List<Boolean>, Integer> paramsToVersion = Map.of(
List.of(true, true), 1,
List.of(false, false), 2,
List.of(true, false), 3,
List.of(false, true), 4);
Now finding the right version is a simple map lookup:
version = paramsToVersion.get(List.of(param1, param2));
The way I initialized the map works since Java 9. In older Java versions it’s a little more wordy, but probably still worth doing. Even in Java 9 you need to use Map.ofEntries
if you have 4 or more parameters (for 16 combinations), which is a little more wordy too.
Original answer:
My taste would be for nested if
/else
statements and only testing each parameter once:
if (param1)
if (param2)
version = 1;
else
version = 3;
else
if (param2)
version = 4;
else
version = 2;
But it scales poorly to many parameters.
I don't like the new solution because you will have to generate up to 2^k lists for k parameters. This is unreadable, and the expansion of the lists is error prone.
– Yves Daoust
Feb 16 at 16:36
@YvesDaoust Then I’m glad that I let my old solution stand here too. I suppose each has its place depending on requirements and circumstances. At least if you add 2^k lists and get a param value wrong, in Java 9Map.of
orMap.ofEntries
will complain about the resulting duplicate kay so you know there’s an error and you need to fix it.
– Ole V.V.
Feb 16 at 16:41
1
This kind of error can be spotted at a glance as the values appear explicitly. What I am referring to is how you expand "(tall and not fat) or old and green" without a mistake, and how you can read that back from the truth table.
– Yves Daoust
Feb 16 at 16:43
@Ole V.V. Yes these are better solutions than mine but scalability concern is still there.
– Ryan Gusto
Feb 17 at 2:34
add a comment |
EDIT:
For a scalable solution define the versions for each parameter combination through a Map
:
Map<List<Boolean>, Integer> paramsToVersion = Map.of(
List.of(true, true), 1,
List.of(false, false), 2,
List.of(true, false), 3,
List.of(false, true), 4);
Now finding the right version is a simple map lookup:
version = paramsToVersion.get(List.of(param1, param2));
The way I initialized the map works since Java 9. In older Java versions it’s a little more wordy, but probably still worth doing. Even in Java 9 you need to use Map.ofEntries
if you have 4 or more parameters (for 16 combinations), which is a little more wordy too.
Original answer:
My taste would be for nested if
/else
statements and only testing each parameter once:
if (param1)
if (param2)
version = 1;
else
version = 3;
else
if (param2)
version = 4;
else
version = 2;
But it scales poorly to many parameters.
EDIT:
For a scalable solution define the versions for each parameter combination through a Map
:
Map<List<Boolean>, Integer> paramsToVersion = Map.of(
List.of(true, true), 1,
List.of(false, false), 2,
List.of(true, false), 3,
List.of(false, true), 4);
Now finding the right version is a simple map lookup:
version = paramsToVersion.get(List.of(param1, param2));
The way I initialized the map works since Java 9. In older Java versions it’s a little more wordy, but probably still worth doing. Even in Java 9 you need to use Map.ofEntries
if you have 4 or more parameters (for 16 combinations), which is a little more wordy too.
Original answer:
My taste would be for nested if
/else
statements and only testing each parameter once:
if (param1)
if (param2)
version = 1;
else
version = 3;
else
if (param2)
version = 4;
else
version = 2;
But it scales poorly to many parameters.
edited Feb 16 at 14:23
answered Feb 16 at 14:15
Ole V.V.Ole V.V.
30.5k63856
30.5k63856
I don't like the new solution because you will have to generate up to 2^k lists for k parameters. This is unreadable, and the expansion of the lists is error prone.
– Yves Daoust
Feb 16 at 16:36
@YvesDaoust Then I’m glad that I let my old solution stand here too. I suppose each has its place depending on requirements and circumstances. At least if you add 2^k lists and get a param value wrong, in Java 9Map.of
orMap.ofEntries
will complain about the resulting duplicate kay so you know there’s an error and you need to fix it.
– Ole V.V.
Feb 16 at 16:41
1
This kind of error can be spotted at a glance as the values appear explicitly. What I am referring to is how you expand "(tall and not fat) or old and green" without a mistake, and how you can read that back from the truth table.
– Yves Daoust
Feb 16 at 16:43
@Ole V.V. Yes these are better solutions than mine but scalability concern is still there.
– Ryan Gusto
Feb 17 at 2:34
add a comment |
I don't like the new solution because you will have to generate up to 2^k lists for k parameters. This is unreadable, and the expansion of the lists is error prone.
– Yves Daoust
Feb 16 at 16:36
@YvesDaoust Then I’m glad that I let my old solution stand here too. I suppose each has its place depending on requirements and circumstances. At least if you add 2^k lists and get a param value wrong, in Java 9Map.of
orMap.ofEntries
will complain about the resulting duplicate kay so you know there’s an error and you need to fix it.
– Ole V.V.
Feb 16 at 16:41
1
This kind of error can be spotted at a glance as the values appear explicitly. What I am referring to is how you expand "(tall and not fat) or old and green" without a mistake, and how you can read that back from the truth table.
– Yves Daoust
Feb 16 at 16:43
@Ole V.V. Yes these are better solutions than mine but scalability concern is still there.
– Ryan Gusto
Feb 17 at 2:34
I don't like the new solution because you will have to generate up to 2^k lists for k parameters. This is unreadable, and the expansion of the lists is error prone.
– Yves Daoust
Feb 16 at 16:36
I don't like the new solution because you will have to generate up to 2^k lists for k parameters. This is unreadable, and the expansion of the lists is error prone.
– Yves Daoust
Feb 16 at 16:36
@YvesDaoust Then I’m glad that I let my old solution stand here too. I suppose each has its place depending on requirements and circumstances. At least if you add 2^k lists and get a param value wrong, in Java 9
Map.of
or Map.ofEntries
will complain about the resulting duplicate kay so you know there’s an error and you need to fix it.– Ole V.V.
Feb 16 at 16:41
@YvesDaoust Then I’m glad that I let my old solution stand here too. I suppose each has its place depending on requirements and circumstances. At least if you add 2^k lists and get a param value wrong, in Java 9
Map.of
or Map.ofEntries
will complain about the resulting duplicate kay so you know there’s an error and you need to fix it.– Ole V.V.
Feb 16 at 16:41
1
1
This kind of error can be spotted at a glance as the values appear explicitly. What I am referring to is how you expand "(tall and not fat) or old and green" without a mistake, and how you can read that back from the truth table.
– Yves Daoust
Feb 16 at 16:43
This kind of error can be spotted at a glance as the values appear explicitly. What I am referring to is how you expand "(tall and not fat) or old and green" without a mistake, and how you can read that back from the truth table.
– Yves Daoust
Feb 16 at 16:43
@Ole V.V. Yes these are better solutions than mine but scalability concern is still there.
– Ryan Gusto
Feb 17 at 2:34
@Ole V.V. Yes these are better solutions than mine but scalability concern is still there.
– Ryan Gusto
Feb 17 at 2:34
add a comment |
If you have to enumerate all the possible combinations of Booleans, it's often simplest to convert them into a number:
// param1: F T F T
// param2; F F T T
static final int VERSIONS = new int2, 3, 4, 1;
...
version = VERSIONS[(param1 ? 1:0) + (param2 ? 2:0)];
@Lino: that won't work,i
will always stay0
, no matter how often you shift it left.
– Ralf Kleberhoff
Feb 16 at 14:12
7
This is really clever, but far from being readable and expressive. For a developer that is new to this code, it might even result cryptic.
– Federico Peralta Schaffner
Feb 16 at 16:32
@FedericoPeraltaSchaffner agreed, but there are readable variants and/or ways to comment it. I'm just leaving that to the OP, since I would like a more concrete example before suggesting a best way.
– Matt Timmermans
Feb 16 at 17:56
I think the answer would benefit from including a comment or an example showing how to extend this beyond two parameters; e.g.(param3 ? 4:0) + (param4 ? 8:0) + ...
, as it may not be clear to some that you are treating the bool sequence as a bit string.
– Filip Milovanović
Feb 16 at 18:29
I'm not sure this passes either the scalable or readable stated requirements. Ok, it might be technically scalable but as we'd add to the list of ternaryif
s, the expression evaluating the index will very quickly get unreadable (to me it already is, which doesn't say much about me I guess :)
– גלעד ברקן
Feb 17 at 12:02
add a comment |
If you have to enumerate all the possible combinations of Booleans, it's often simplest to convert them into a number:
// param1: F T F T
// param2; F F T T
static final int VERSIONS = new int2, 3, 4, 1;
...
version = VERSIONS[(param1 ? 1:0) + (param2 ? 2:0)];
@Lino: that won't work,i
will always stay0
, no matter how often you shift it left.
– Ralf Kleberhoff
Feb 16 at 14:12
7
This is really clever, but far from being readable and expressive. For a developer that is new to this code, it might even result cryptic.
– Federico Peralta Schaffner
Feb 16 at 16:32
@FedericoPeraltaSchaffner agreed, but there are readable variants and/or ways to comment it. I'm just leaving that to the OP, since I would like a more concrete example before suggesting a best way.
– Matt Timmermans
Feb 16 at 17:56
I think the answer would benefit from including a comment or an example showing how to extend this beyond two parameters; e.g.(param3 ? 4:0) + (param4 ? 8:0) + ...
, as it may not be clear to some that you are treating the bool sequence as a bit string.
– Filip Milovanović
Feb 16 at 18:29
I'm not sure this passes either the scalable or readable stated requirements. Ok, it might be technically scalable but as we'd add to the list of ternaryif
s, the expression evaluating the index will very quickly get unreadable (to me it already is, which doesn't say much about me I guess :)
– גלעד ברקן
Feb 17 at 12:02
add a comment |
If you have to enumerate all the possible combinations of Booleans, it's often simplest to convert them into a number:
// param1: F T F T
// param2; F F T T
static final int VERSIONS = new int2, 3, 4, 1;
...
version = VERSIONS[(param1 ? 1:0) + (param2 ? 2:0)];
If you have to enumerate all the possible combinations of Booleans, it's often simplest to convert them into a number:
// param1: F T F T
// param2; F F T T
static final int VERSIONS = new int2, 3, 4, 1;
...
version = VERSIONS[(param1 ? 1:0) + (param2 ? 2:0)];
edited Feb 17 at 4:22
answered Feb 16 at 13:29
Matt TimmermansMatt Timmermans
20.6k11733
20.6k11733
@Lino: that won't work,i
will always stay0
, no matter how often you shift it left.
– Ralf Kleberhoff
Feb 16 at 14:12
7
This is really clever, but far from being readable and expressive. For a developer that is new to this code, it might even result cryptic.
– Federico Peralta Schaffner
Feb 16 at 16:32
@FedericoPeraltaSchaffner agreed, but there are readable variants and/or ways to comment it. I'm just leaving that to the OP, since I would like a more concrete example before suggesting a best way.
– Matt Timmermans
Feb 16 at 17:56
I think the answer would benefit from including a comment or an example showing how to extend this beyond two parameters; e.g.(param3 ? 4:0) + (param4 ? 8:0) + ...
, as it may not be clear to some that you are treating the bool sequence as a bit string.
– Filip Milovanović
Feb 16 at 18:29
I'm not sure this passes either the scalable or readable stated requirements. Ok, it might be technically scalable but as we'd add to the list of ternaryif
s, the expression evaluating the index will very quickly get unreadable (to me it already is, which doesn't say much about me I guess :)
– גלעד ברקן
Feb 17 at 12:02
add a comment |
@Lino: that won't work,i
will always stay0
, no matter how often you shift it left.
– Ralf Kleberhoff
Feb 16 at 14:12
7
This is really clever, but far from being readable and expressive. For a developer that is new to this code, it might even result cryptic.
– Federico Peralta Schaffner
Feb 16 at 16:32
@FedericoPeraltaSchaffner agreed, but there are readable variants and/or ways to comment it. I'm just leaving that to the OP, since I would like a more concrete example before suggesting a best way.
– Matt Timmermans
Feb 16 at 17:56
I think the answer would benefit from including a comment or an example showing how to extend this beyond two parameters; e.g.(param3 ? 4:0) + (param4 ? 8:0) + ...
, as it may not be clear to some that you are treating the bool sequence as a bit string.
– Filip Milovanović
Feb 16 at 18:29
I'm not sure this passes either the scalable or readable stated requirements. Ok, it might be technically scalable but as we'd add to the list of ternaryif
s, the expression evaluating the index will very quickly get unreadable (to me it already is, which doesn't say much about me I guess :)
– גלעד ברקן
Feb 17 at 12:02
@Lino: that won't work,
i
will always stay 0
, no matter how often you shift it left.– Ralf Kleberhoff
Feb 16 at 14:12
@Lino: that won't work,
i
will always stay 0
, no matter how often you shift it left.– Ralf Kleberhoff
Feb 16 at 14:12
7
7
This is really clever, but far from being readable and expressive. For a developer that is new to this code, it might even result cryptic.
– Federico Peralta Schaffner
Feb 16 at 16:32
This is really clever, but far from being readable and expressive. For a developer that is new to this code, it might even result cryptic.
– Federico Peralta Schaffner
Feb 16 at 16:32
@FedericoPeraltaSchaffner agreed, but there are readable variants and/or ways to comment it. I'm just leaving that to the OP, since I would like a more concrete example before suggesting a best way.
– Matt Timmermans
Feb 16 at 17:56
@FedericoPeraltaSchaffner agreed, but there are readable variants and/or ways to comment it. I'm just leaving that to the OP, since I would like a more concrete example before suggesting a best way.
– Matt Timmermans
Feb 16 at 17:56
I think the answer would benefit from including a comment or an example showing how to extend this beyond two parameters; e.g.
(param3 ? 4:0) + (param4 ? 8:0) + ...
, as it may not be clear to some that you are treating the bool sequence as a bit string.– Filip Milovanović
Feb 16 at 18:29
I think the answer would benefit from including a comment or an example showing how to extend this beyond two parameters; e.g.
(param3 ? 4:0) + (param4 ? 8:0) + ...
, as it may not be clear to some that you are treating the bool sequence as a bit string.– Filip Milovanović
Feb 16 at 18:29
I'm not sure this passes either the scalable or readable stated requirements. Ok, it might be technically scalable but as we'd add to the list of ternary
if
s, the expression evaluating the index will very quickly get unreadable (to me it already is, which doesn't say much about me I guess :)– גלעד ברקן
Feb 17 at 12:02
I'm not sure this passes either the scalable or readable stated requirements. Ok, it might be technically scalable but as we'd add to the list of ternary
if
s, the expression evaluating the index will very quickly get unreadable (to me it already is, which doesn't say much about me I guess :)– גלעד ברקן
Feb 17 at 12:02
add a comment |
I doubt that there is a way that would be more compact, readable and scalable at the same time.
You express the conditions as minimized expressions, which are compact and may have meaning (in particular, the irrelevant variables don't clutter them). But there is no systematism that you could exploit.
A quite systematic alternative could be truth tables, i.e. the explicit expansion of all combinations and the associated truth value (or version number), which can be very efficient in terms of running-time. But these have a size exponential in the number of variables and are not especially readable.
I am afraid there is no free lunch. Your current solution is excellent.
If you are after efficiency (i.e. avoiding the need to evaluate all expressions sequentially), then you can think of the truth table approach, but in the following way:
declare an array of version numbers, with 2^n entries;
use the code just like you wrote to initialize all table entries; to achieve that, enumerate all integers in [0, 2^n) and use their binary representation;
now for a query, form an integer index from the n input booleans and lookup the array.
Using the answer by Olevv, the table would be [2, 4, 3, 1]. A lookup would be like (false, true) => T[01b] = 4.
What matters is that the original set of expressions is still there in the code, for human reading. You can use it in an initialization function that will fill the array at run-time, and you can also use it to hard-code the table (and leave the code in comments; even better, leave the code that generates the hard-coded table).
add a comment |
I doubt that there is a way that would be more compact, readable and scalable at the same time.
You express the conditions as minimized expressions, which are compact and may have meaning (in particular, the irrelevant variables don't clutter them). But there is no systematism that you could exploit.
A quite systematic alternative could be truth tables, i.e. the explicit expansion of all combinations and the associated truth value (or version number), which can be very efficient in terms of running-time. But these have a size exponential in the number of variables and are not especially readable.
I am afraid there is no free lunch. Your current solution is excellent.
If you are after efficiency (i.e. avoiding the need to evaluate all expressions sequentially), then you can think of the truth table approach, but in the following way:
declare an array of version numbers, with 2^n entries;
use the code just like you wrote to initialize all table entries; to achieve that, enumerate all integers in [0, 2^n) and use their binary representation;
now for a query, form an integer index from the n input booleans and lookup the array.
Using the answer by Olevv, the table would be [2, 4, 3, 1]. A lookup would be like (false, true) => T[01b] = 4.
What matters is that the original set of expressions is still there in the code, for human reading. You can use it in an initialization function that will fill the array at run-time, and you can also use it to hard-code the table (and leave the code in comments; even better, leave the code that generates the hard-coded table).
add a comment |
I doubt that there is a way that would be more compact, readable and scalable at the same time.
You express the conditions as minimized expressions, which are compact and may have meaning (in particular, the irrelevant variables don't clutter them). But there is no systematism that you could exploit.
A quite systematic alternative could be truth tables, i.e. the explicit expansion of all combinations and the associated truth value (or version number), which can be very efficient in terms of running-time. But these have a size exponential in the number of variables and are not especially readable.
I am afraid there is no free lunch. Your current solution is excellent.
If you are after efficiency (i.e. avoiding the need to evaluate all expressions sequentially), then you can think of the truth table approach, but in the following way:
declare an array of version numbers, with 2^n entries;
use the code just like you wrote to initialize all table entries; to achieve that, enumerate all integers in [0, 2^n) and use their binary representation;
now for a query, form an integer index from the n input booleans and lookup the array.
Using the answer by Olevv, the table would be [2, 4, 3, 1]. A lookup would be like (false, true) => T[01b] = 4.
What matters is that the original set of expressions is still there in the code, for human reading. You can use it in an initialization function that will fill the array at run-time, and you can also use it to hard-code the table (and leave the code in comments; even better, leave the code that generates the hard-coded table).
I doubt that there is a way that would be more compact, readable and scalable at the same time.
You express the conditions as minimized expressions, which are compact and may have meaning (in particular, the irrelevant variables don't clutter them). But there is no systematism that you could exploit.
A quite systematic alternative could be truth tables, i.e. the explicit expansion of all combinations and the associated truth value (or version number), which can be very efficient in terms of running-time. But these have a size exponential in the number of variables and are not especially readable.
I am afraid there is no free lunch. Your current solution is excellent.
If you are after efficiency (i.e. avoiding the need to evaluate all expressions sequentially), then you can think of the truth table approach, but in the following way:
declare an array of version numbers, with 2^n entries;
use the code just like you wrote to initialize all table entries; to achieve that, enumerate all integers in [0, 2^n) and use their binary representation;
now for a query, form an integer index from the n input booleans and lookup the array.
Using the answer by Olevv, the table would be [2, 4, 3, 1]. A lookup would be like (false, true) => T[01b] = 4.
What matters is that the original set of expressions is still there in the code, for human reading. You can use it in an initialization function that will fill the array at run-time, and you can also use it to hard-code the table (and leave the code in comments; even better, leave the code that generates the hard-coded table).
edited Feb 16 at 16:55
answered Feb 16 at 16:18
Yves DaoustYves Daoust
38.1k72759
38.1k72759
add a comment |
add a comment |
Your combinations of parameters is nothing more than a binary number (like 01100
) where the 0
indicates a false
and the 1
a true
.
So your version can be easily calculated by using all the combinations of ones and zeroes. Possible combinations with 2 input parameters are:
11
-> both aretrue
10
-> first istrue
, second isfalse
01
-> first isfalse
, second istrue
00
-> both arefalse
So with this knowledge I've come up with a quite scalable solution using a "bit mask" (nothing more than a number) and "bit operations":
public static int getVersion(boolean... params)
int length = params.length;
int mask = (1 << length) - 1;
for(int i = 0; i < length; i++)
if(!params[i])
mask &= ~(1 << length - i - 1);
return mask + 1;
The most interesting line is probably this:
mask &= ~(1 << length - i - 1);
It does many things at once, I split it up. The part length - i - 1
calculates the position of the "bit" inside the bit mask from the right (0
based, like in arrays).
The next part: 1 << (length - i - 1)
shifts the number 1
the amount of positions to the left. So lets say we have a position of 3, then the result of the operation 1 << 2
(2
is the third position) would be a binary number of the value 100
.
The ~
sign is a binary inverse, so all the bits are inverted, all 0
are turned to 1
and all 1
are turned to 0
. With the previous example the inverse of 100
would be 011
.
The last part: mask &= n
is the same as mask = mask & n
where n
is the previously computed value 011
. This is nothing more than a binary AND, so all the same bits which are in mask
and in n
are kept, where as all others are discarded.
All in all, does this single line nothing more than remove the "bit" at a given position of the mask
if the input parameter is false
.
If the version numbers are not sequential from 1
to 4
then a version lookup table, like this one may help you.
The whole code would need just a single adjustment in the last line:
return VERSIONS[mask];
Where your VERSIONS
array consists of all the versions in order, but reversed. (index 0
of VERSIONS
is where both parameters are false)
2
I don't really care about downvotes, but may the downvoter mention why? So I could improve the answer if needed
– Lino
Feb 16 at 17:27
2
Very solid approach.
– user58697
Feb 16 at 17:46
I didn't downvote this, but this does look a bit convoluted so I wouldn't be surprised that someone thought it downvote-worthy. Part of it might be the negative logic; it might feel more natural to just set the value to zero to start with, and then set the bits as necessary. Also, I think you could make the(1 << length - i - 1)
clearer by running the loop downwards, not up and then just have(1 << i)
.
– ilkkachu
Feb 16 at 22:52
Even more so, doesint mask = length * 2 - 1;
work? If there are three items in the list, this givesmask = 5
, and 5 is0101
and I'm not sure how that's useful?
– ilkkachu
Feb 16 at 22:54
How is this readable (a stated requirement by the OP)? "Readable" to me would mean being able to easily follow how the set of params, and each individual one, contributes to the expression evaluating the version. I can't find a place like that in the code snippet. (I did not downvote.)
– גלעד ברקן
Feb 17 at 15:23
add a comment |
Your combinations of parameters is nothing more than a binary number (like 01100
) where the 0
indicates a false
and the 1
a true
.
So your version can be easily calculated by using all the combinations of ones and zeroes. Possible combinations with 2 input parameters are:
11
-> both aretrue
10
-> first istrue
, second isfalse
01
-> first isfalse
, second istrue
00
-> both arefalse
So with this knowledge I've come up with a quite scalable solution using a "bit mask" (nothing more than a number) and "bit operations":
public static int getVersion(boolean... params)
int length = params.length;
int mask = (1 << length) - 1;
for(int i = 0; i < length; i++)
if(!params[i])
mask &= ~(1 << length - i - 1);
return mask + 1;
The most interesting line is probably this:
mask &= ~(1 << length - i - 1);
It does many things at once, I split it up. The part length - i - 1
calculates the position of the "bit" inside the bit mask from the right (0
based, like in arrays).
The next part: 1 << (length - i - 1)
shifts the number 1
the amount of positions to the left. So lets say we have a position of 3, then the result of the operation 1 << 2
(2
is the third position) would be a binary number of the value 100
.
The ~
sign is a binary inverse, so all the bits are inverted, all 0
are turned to 1
and all 1
are turned to 0
. With the previous example the inverse of 100
would be 011
.
The last part: mask &= n
is the same as mask = mask & n
where n
is the previously computed value 011
. This is nothing more than a binary AND, so all the same bits which are in mask
and in n
are kept, where as all others are discarded.
All in all, does this single line nothing more than remove the "bit" at a given position of the mask
if the input parameter is false
.
If the version numbers are not sequential from 1
to 4
then a version lookup table, like this one may help you.
The whole code would need just a single adjustment in the last line:
return VERSIONS[mask];
Where your VERSIONS
array consists of all the versions in order, but reversed. (index 0
of VERSIONS
is where both parameters are false)
2
I don't really care about downvotes, but may the downvoter mention why? So I could improve the answer if needed
– Lino
Feb 16 at 17:27
2
Very solid approach.
– user58697
Feb 16 at 17:46
I didn't downvote this, but this does look a bit convoluted so I wouldn't be surprised that someone thought it downvote-worthy. Part of it might be the negative logic; it might feel more natural to just set the value to zero to start with, and then set the bits as necessary. Also, I think you could make the(1 << length - i - 1)
clearer by running the loop downwards, not up and then just have(1 << i)
.
– ilkkachu
Feb 16 at 22:52
Even more so, doesint mask = length * 2 - 1;
work? If there are three items in the list, this givesmask = 5
, and 5 is0101
and I'm not sure how that's useful?
– ilkkachu
Feb 16 at 22:54
How is this readable (a stated requirement by the OP)? "Readable" to me would mean being able to easily follow how the set of params, and each individual one, contributes to the expression evaluating the version. I can't find a place like that in the code snippet. (I did not downvote.)
– גלעד ברקן
Feb 17 at 15:23
add a comment |
Your combinations of parameters is nothing more than a binary number (like 01100
) where the 0
indicates a false
and the 1
a true
.
So your version can be easily calculated by using all the combinations of ones and zeroes. Possible combinations with 2 input parameters are:
11
-> both aretrue
10
-> first istrue
, second isfalse
01
-> first isfalse
, second istrue
00
-> both arefalse
So with this knowledge I've come up with a quite scalable solution using a "bit mask" (nothing more than a number) and "bit operations":
public static int getVersion(boolean... params)
int length = params.length;
int mask = (1 << length) - 1;
for(int i = 0; i < length; i++)
if(!params[i])
mask &= ~(1 << length - i - 1);
return mask + 1;
The most interesting line is probably this:
mask &= ~(1 << length - i - 1);
It does many things at once, I split it up. The part length - i - 1
calculates the position of the "bit" inside the bit mask from the right (0
based, like in arrays).
The next part: 1 << (length - i - 1)
shifts the number 1
the amount of positions to the left. So lets say we have a position of 3, then the result of the operation 1 << 2
(2
is the third position) would be a binary number of the value 100
.
The ~
sign is a binary inverse, so all the bits are inverted, all 0
are turned to 1
and all 1
are turned to 0
. With the previous example the inverse of 100
would be 011
.
The last part: mask &= n
is the same as mask = mask & n
where n
is the previously computed value 011
. This is nothing more than a binary AND, so all the same bits which are in mask
and in n
are kept, where as all others are discarded.
All in all, does this single line nothing more than remove the "bit" at a given position of the mask
if the input parameter is false
.
If the version numbers are not sequential from 1
to 4
then a version lookup table, like this one may help you.
The whole code would need just a single adjustment in the last line:
return VERSIONS[mask];
Where your VERSIONS
array consists of all the versions in order, but reversed. (index 0
of VERSIONS
is where both parameters are false)
Your combinations of parameters is nothing more than a binary number (like 01100
) where the 0
indicates a false
and the 1
a true
.
So your version can be easily calculated by using all the combinations of ones and zeroes. Possible combinations with 2 input parameters are:
11
-> both aretrue
10
-> first istrue
, second isfalse
01
-> first isfalse
, second istrue
00
-> both arefalse
So with this knowledge I've come up with a quite scalable solution using a "bit mask" (nothing more than a number) and "bit operations":
public static int getVersion(boolean... params)
int length = params.length;
int mask = (1 << length) - 1;
for(int i = 0; i < length; i++)
if(!params[i])
mask &= ~(1 << length - i - 1);
return mask + 1;
The most interesting line is probably this:
mask &= ~(1 << length - i - 1);
It does many things at once, I split it up. The part length - i - 1
calculates the position of the "bit" inside the bit mask from the right (0
based, like in arrays).
The next part: 1 << (length - i - 1)
shifts the number 1
the amount of positions to the left. So lets say we have a position of 3, then the result of the operation 1 << 2
(2
is the third position) would be a binary number of the value 100
.
The ~
sign is a binary inverse, so all the bits are inverted, all 0
are turned to 1
and all 1
are turned to 0
. With the previous example the inverse of 100
would be 011
.
The last part: mask &= n
is the same as mask = mask & n
where n
is the previously computed value 011
. This is nothing more than a binary AND, so all the same bits which are in mask
and in n
are kept, where as all others are discarded.
All in all, does this single line nothing more than remove the "bit" at a given position of the mask
if the input parameter is false
.
If the version numbers are not sequential from 1
to 4
then a version lookup table, like this one may help you.
The whole code would need just a single adjustment in the last line:
return VERSIONS[mask];
Where your VERSIONS
array consists of all the versions in order, but reversed. (index 0
of VERSIONS
is where both parameters are false)
edited Feb 17 at 13:21
answered Feb 16 at 16:53
LinoLino
9,92722043
9,92722043
2
I don't really care about downvotes, but may the downvoter mention why? So I could improve the answer if needed
– Lino
Feb 16 at 17:27
2
Very solid approach.
– user58697
Feb 16 at 17:46
I didn't downvote this, but this does look a bit convoluted so I wouldn't be surprised that someone thought it downvote-worthy. Part of it might be the negative logic; it might feel more natural to just set the value to zero to start with, and then set the bits as necessary. Also, I think you could make the(1 << length - i - 1)
clearer by running the loop downwards, not up and then just have(1 << i)
.
– ilkkachu
Feb 16 at 22:52
Even more so, doesint mask = length * 2 - 1;
work? If there are three items in the list, this givesmask = 5
, and 5 is0101
and I'm not sure how that's useful?
– ilkkachu
Feb 16 at 22:54
How is this readable (a stated requirement by the OP)? "Readable" to me would mean being able to easily follow how the set of params, and each individual one, contributes to the expression evaluating the version. I can't find a place like that in the code snippet. (I did not downvote.)
– גלעד ברקן
Feb 17 at 15:23
add a comment |
2
I don't really care about downvotes, but may the downvoter mention why? So I could improve the answer if needed
– Lino
Feb 16 at 17:27
2
Very solid approach.
– user58697
Feb 16 at 17:46
I didn't downvote this, but this does look a bit convoluted so I wouldn't be surprised that someone thought it downvote-worthy. Part of it might be the negative logic; it might feel more natural to just set the value to zero to start with, and then set the bits as necessary. Also, I think you could make the(1 << length - i - 1)
clearer by running the loop downwards, not up and then just have(1 << i)
.
– ilkkachu
Feb 16 at 22:52
Even more so, doesint mask = length * 2 - 1;
work? If there are three items in the list, this givesmask = 5
, and 5 is0101
and I'm not sure how that's useful?
– ilkkachu
Feb 16 at 22:54
How is this readable (a stated requirement by the OP)? "Readable" to me would mean being able to easily follow how the set of params, and each individual one, contributes to the expression evaluating the version. I can't find a place like that in the code snippet. (I did not downvote.)
– גלעד ברקן
Feb 17 at 15:23
2
2
I don't really care about downvotes, but may the downvoter mention why? So I could improve the answer if needed
– Lino
Feb 16 at 17:27
I don't really care about downvotes, but may the downvoter mention why? So I could improve the answer if needed
– Lino
Feb 16 at 17:27
2
2
Very solid approach.
– user58697
Feb 16 at 17:46
Very solid approach.
– user58697
Feb 16 at 17:46
I didn't downvote this, but this does look a bit convoluted so I wouldn't be surprised that someone thought it downvote-worthy. Part of it might be the negative logic; it might feel more natural to just set the value to zero to start with, and then set the bits as necessary. Also, I think you could make the
(1 << length - i - 1)
clearer by running the loop downwards, not up and then just have (1 << i)
.– ilkkachu
Feb 16 at 22:52
I didn't downvote this, but this does look a bit convoluted so I wouldn't be surprised that someone thought it downvote-worthy. Part of it might be the negative logic; it might feel more natural to just set the value to zero to start with, and then set the bits as necessary. Also, I think you could make the
(1 << length - i - 1)
clearer by running the loop downwards, not up and then just have (1 << i)
.– ilkkachu
Feb 16 at 22:52
Even more so, does
int mask = length * 2 - 1;
work? If there are three items in the list, this gives mask = 5
, and 5 is 0101
and I'm not sure how that's useful?– ilkkachu
Feb 16 at 22:54
Even more so, does
int mask = length * 2 - 1;
work? If there are three items in the list, this gives mask = 5
, and 5 is 0101
and I'm not sure how that's useful?– ilkkachu
Feb 16 at 22:54
How is this readable (a stated requirement by the OP)? "Readable" to me would mean being able to easily follow how the set of params, and each individual one, contributes to the expression evaluating the version. I can't find a place like that in the code snippet. (I did not downvote.)
– גלעד ברקן
Feb 17 at 15:23
How is this readable (a stated requirement by the OP)? "Readable" to me would mean being able to easily follow how the set of params, and each individual one, contributes to the expression evaluating the version. I can't find a place like that in the code snippet. (I did not downvote.)
– גלעד ברקן
Feb 17 at 15:23
add a comment |
I would have just gone with:
if (param1)
if (param2)
else
else
if (param2)
else
Kind of repetitive, but each condition is evaluated only once, and you can easily find the code that executes for any particular combination. Adding a 3rd parameter will, of course, double the code. But if there are any invalid combinations, you can leave those out which shortens the code. Or, if you want to throw an exception for them, it becomes fairly easy to see which combination you have missed. When the IF's become too long, you can bring the actual code out in methods:
if (param1)
if (param2)
method_12();
else
method_1();
else
if (param2)
method_2();
else
method_none();
Thus your whole switching logic takes up a function of itself and the actual code for any combination is in another method. When you need to work with the code for a particular combination, you just look up the appropriate method. The big IF maze is then rarely looked at, and when it is, it contains only the IFs themselves and nothing else potentially distracting.
add a comment |
I would have just gone with:
if (param1)
if (param2)
else
else
if (param2)
else
Kind of repetitive, but each condition is evaluated only once, and you can easily find the code that executes for any particular combination. Adding a 3rd parameter will, of course, double the code. But if there are any invalid combinations, you can leave those out which shortens the code. Or, if you want to throw an exception for them, it becomes fairly easy to see which combination you have missed. When the IF's become too long, you can bring the actual code out in methods:
if (param1)
if (param2)
method_12();
else
method_1();
else
if (param2)
method_2();
else
method_none();
Thus your whole switching logic takes up a function of itself and the actual code for any combination is in another method. When you need to work with the code for a particular combination, you just look up the appropriate method. The big IF maze is then rarely looked at, and when it is, it contains only the IFs themselves and nothing else potentially distracting.
add a comment |
I would have just gone with:
if (param1)
if (param2)
else
else
if (param2)
else
Kind of repetitive, but each condition is evaluated only once, and you can easily find the code that executes for any particular combination. Adding a 3rd parameter will, of course, double the code. But if there are any invalid combinations, you can leave those out which shortens the code. Or, if you want to throw an exception for them, it becomes fairly easy to see which combination you have missed. When the IF's become too long, you can bring the actual code out in methods:
if (param1)
if (param2)
method_12();
else
method_1();
else
if (param2)
method_2();
else
method_none();
Thus your whole switching logic takes up a function of itself and the actual code for any combination is in another method. When you need to work with the code for a particular combination, you just look up the appropriate method. The big IF maze is then rarely looked at, and when it is, it contains only the IFs themselves and nothing else potentially distracting.
I would have just gone with:
if (param1)
if (param2)
else
else
if (param2)
else
Kind of repetitive, but each condition is evaluated only once, and you can easily find the code that executes for any particular combination. Adding a 3rd parameter will, of course, double the code. But if there are any invalid combinations, you can leave those out which shortens the code. Or, if you want to throw an exception for them, it becomes fairly easy to see which combination you have missed. When the IF's become too long, you can bring the actual code out in methods:
if (param1)
if (param2)
method_12();
else
method_1();
else
if (param2)
method_2();
else
method_none();
Thus your whole switching logic takes up a function of itself and the actual code for any combination is in another method. When you need to work with the code for a particular combination, you just look up the appropriate method. The big IF maze is then rarely looked at, and when it is, it contains only the IFs themselves and nothing else potentially distracting.
answered Feb 16 at 19:36
Vilx-Vilx-
61.5k71234377
61.5k71234377
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54723382%2fhow-to-code-these-conditional-statements-in-more-elegant-scalable-manner%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Are yo usure that the if/else if cascade is correct ? Because if some test returns true, the next won't be evaluated at all.
– Yves Daoust
Feb 16 at 16:11
@YvesDaoust Seems correct, doesn't it? I think it is desired that only one
if
body is visited– Lino
Feb 16 at 16:18
@Lino: mutual exclusiveness of the expressions must be guaranteed then.
– Yves Daoust
Feb 16 at 16:22
What is the expected result with
param3
? Can you describe the pattern change generally as we add params?– גלעד ברקן
Feb 16 at 16:28
Do you plan to increase versions as well?
– Nitin
Feb 16 at 19:53