#1 11 Feb 2021 09:03

Rekrul
Member
Registered: 17 Apr 2016
Posts: 85

IF/ELSE vs. multiple IFs?

When testing multiple conditions, is there any advantage to nesting multiple IF comparisons using ELSE, rather than simply using multiple IF lines?

In other words, is there any advantage to using this;

if x equ %1% (echo ONE) else (if %x% equ 2 (echo TWO) else (if %x% equ 3 echo THREE))

Over this;

if %x% equ 1 echo ONE
if %x% equ 2 echo TWO
if %x% equ 3 echo THREE

I suppose the first would be marginally faster if x happened to be 1 or 2, since it wouldn't execute the rest of the line, whereas the second one would always execute all three, but unless that section of the script was being executed thousands of times, I can't imagine the difference being enough to matter.

Offline

#2 11 Feb 2021 22:52

T3RRY
Member
Registered: 15 Oct 2020
Posts: 10

Re: IF/ELSE vs. multiple IFs?

For readabilities and maintenance's sake, I'd not recommend same line chaining of If else statements except perhaps in the definition macro functions provided they don't require too long a line.
The most common issue with using Nested if Conditions is the delayed expansion "trap" that catches so many new scripters out; Using subsequent If statements outside of command blocks avoids the need to use delayed expansion, however it's not often that's necessary.

Generally, for the type of conditional execution you've exampled, and especially when there's a large number of tests to perform, Definition of arrays and expansion of the content using the relevent index is far more efficient, especially when the actions are repetative.
A script that Illustrates the use of [where batch is concerned] advanced conditional execution through the use of Arrays is my 48 line Tic Tac toe.

Out of curiosity I've searched out numerous other attempts at Tic Tac Toe using batch. I've found one so far that uses the majority of the same constructs, yet still comes in at a whopping 245 lines.

Where your example is concerned, you could do the following:

 @Echo off
  Set "Def.Array=For %%n in (1 2)Do if %%n==2 ((If "!#$A!"=="" (Set "#$A=1"))&(For %%G in (!elements!)Do (Set "$A[!#$A!]=%%~G"&Set /A "#$A+=1")))Else Set elements="
 Setlocal EnableDelayedExpansion
  %Def.Array:$A=Number%One Two Three Four
  Echo Enter a Number: 1 2 3 4
  For /F "Delims=" %%i in ('Choice /N /C:1234')Do Echo/!Number[%%i]!
 Endlocal

Last edited by T3RRY (11 Feb 2021 23:30)

Offline

#3 12 Feb 2021 06:51

Rekrul
Member
Registered: 17 Apr 2016
Posts: 85

Re: IF/ELSE vs. multiple IFs?

T3RRY wrote:

For readabilities and maintenance's sake, I'd not recommend same line chaining of If else statements except perhaps in the definition macro functions provided they don't require too long a line.

On the one hand, using multiple lines is more readable, but on the other hand, I like that all the relevant commands are handled in one line.

T3RRY wrote:

The most common issue with using Nested if Conditions is the delayed expansion "trap" that catches so many new scripters out;

I've had many problems with delayed expansion. My nested line seems to work OK though.

T3RRY wrote:

Generally, for the type of conditional execution you've exampled, and especially when there's a large number of tests to perform, Definition of arrays and expansion of the content using the relevent index is far more efficient, especially when the actions are repetative.

I was previously warned (I forget if it was here or elsewhere) that arrays were unreliable in Batch.

Generally, I use such lines to cycle values in a variable, 1 > 2 > 3 > 1, etc. I often pair that with a dynamic menu using the Choice command, so that the user only has to press a key to cycle the value, and by clearing the window and conditionally echoing the relevant lines, it looks like the menu is just toggling those lines in real time. It's a simple trick, but it looks slick. smile

Although in truth, I usually only have a need to cycle between two values, usually representing on and off.

Offline

#4 12 Feb 2021 07:34

T3RRY
Member
Registered: 15 Oct 2020
Posts: 10

Re: IF/ELSE vs. multiple IFs?

Rekrul wrote:

I've had many problems with delayed expansion. My nested line seems to work OK though.

The only time delayed expansion is a real issue is when dealing with input data that may contain exclamation marks, which can be handled by toggling Expansion state and testing the input data.

Rekrul wrote:

I was previously warned (I forget if it was here or elsewhere) that arrays were unreliable in Batch.

Arrays in batch are not 'true' arrays. They are simply variables that use a naming convention to asociate a set of values in a way that lets different values be accessed based on the index string that differentiates one array element from another.

Delayed expansion is not the only way to expand array value, however it is the faster performing method.
The time taken to expand an array variable will always be less than the time taken to perform a series of condition tests. This is especially valuable for animations or games where you want to minimise the overhead as much as possible to effect a fast frame rate.

Using For loops of commands that get the index value can also speed things along.
Say you want to access a rabdom index value in a 1 indexed array with for elements:

@Echo off
  Set "Def.Array=For %%n in (1 2)Do if %%n==2 ((If "!#$A!"=="" (Set "#$A=1"))&(For %%G in (!elements!)Do (Set "$A[!#$A!]=%%~G"&Set /A "#$A+=1")))Else Set elements="
 Setlocal EnableDelayedExpansion
  %Def.Array:$A=Number%One Two Three Four
  Echo Enter a Number: 1 2 3 4
  For /F "Delims=" %%i in ('Choice /N /C:1234')Do Echo/!Number[%%i]!
rem echo random array element
  For /F "Delims=" %%i in ('Set /A !random! %%4 + 1')Do Echo(!Number[%%i]!
 Endlocal
Rekrul wrote:

Generally, I use such lines to cycle values in a variable, 1 > 2 > 3 > 1, etc. I often pair that with a dynamic menu using the Choice command, so that the user only has to press a key to cycle the value, and by clearing the window and conditionally echoing the relevant lines, it looks like the menu is just toggling those lines in real time. It's a simple trick, but it looks slick. smile

When dealing with very small data sets only once or twice in a script, there is little benefit to using an array.
When performing repetative actions over medium to large data sets, the efficiency savings of an array as opposed to countless if conditions is enormous, not just in processing speed, but also in how quickly you can write the script.

Last edited by T3RRY (12 Feb 2021 08:05)

Offline

#5 13 Feb 2021 04:46

Shadow Thief
Member
Registered: 12 Jul 2012
Posts: 202

Re: IF/ELSE vs. multiple IFs?

T3RRY wrote:

For readabilities and maintenance's sake, I'd not recommend same line chaining of If else statements except perhaps in the definition macro functions provided they don't require too long a line.
The most common issue with using Nested if Conditions is the delayed expansion "trap" that catches so many new scripters out; Using subsequent If statements outside of command blocks avoids the need to use delayed expansion, however it's not often that's necessary.

Generally, for the type of conditional execution you've exampled, and especially when there's a large number of tests to perform, Definition of arrays and expansion of the content using the relevent index is far more efficient, especially when the actions are repetative.
A script that Illustrates the use of [where batch is concerned] advanced conditional execution through the use of Arrays is my 48 line Tic Tac toe.

Out of curiosity I've searched out numerous other attempts at Tic Tac Toe using batch. I've found one so far that uses the majority of the same constructs, yet still comes in at a whopping 245 lines.

Where your example is concerned, you could do the following:

 @Echo off
  Set "Def.Array=For %%n in (1 2)Do if %%n==2 ((If "!#$A!"=="" (Set "#$A=1"))&(For %%G in (!elements!)Do (Set "$A[!#$A!]=%%~G"&Set /A "#$A+=1")))Else Set elements="
 Setlocal EnableDelayedExpansion
  %Def.Array:$A=Number%One Two Three Four
  Echo Enter a Number: 1 2 3 4
  For /F "Delims=" %%i in ('Choice /N /C:1234')Do Echo/!Number[%%i]!
 Endlocal

I like how you post about readability and maintainability and then post that.

Offline

#6 19 Feb 2021 07:43

Rekrul
Member
Registered: 17 Apr 2016
Posts: 85

Re: IF/ELSE vs. multiple IFs?

T3RRY wrote:

The only time delayed expansion is a real issue is when dealing with input data that may contain exclamation marks,

Or when reading filenames, which may contain them, or when reading lines from a text file.

T3RRY wrote:

which can be handled by toggling Expansion state and testing the input data.

I'm not sure what you mean here. It's my understanding that the only way to toggle Delayed Expansion is by using the Setlocal/Endlocal commands, which creates all sorts of problems for trying to pass variables to the rest of the script.

For example, if you have a For loop that reads lines from a file, you have to enable it AFTER reading a line, but then you need to disable it before the loop repeats again, but using Endlocal & Set doesn't work (that only works outside the loop). You have to include another For command to preserve the value. Which gets to be a pain in the butt if you have multiple values that need to be preserved.

Frankly, it would have solved so many problems if they had simply made the commands to enable/disable Delayed Expansion separate from the Local commands. Just enable/disable it for the entire scripts as needed.

T3RRY wrote:

Using For loops of commands that get the index value can also speed things along.
Say you want to access a rabdom index value in a 1 indexed array with for elements:

I'll be honest, I don't understand any of that.

T3RRY wrote:

When dealing with very small data sets only once or twice in a script, there is little benefit to using an array.
When performing repetative actions over medium to large data sets, the efficiency savings of an array as opposed to countless if conditions is enormous, not just in processing speed, but also in how quickly you can write the script.

I often struggle with simple stuff.

I recently created a script that will read in lines from a large SFV file and split it into multiple smaller ones, based on which lines pertain to which sub-directories. It could read and echo the lines to the screen perfectly, but when I told it to redirect them to a new file it gave me errors. I was just about to post here and ask for help when I found a post on another site mentioning Delayed Expansion. I changed the script to enable it and then it worked.

I probably should have included it from the start just in case of exclamation points in the filenames, but I usually start with the simplest example I can think of to test my theory before getting fancy, I figure why write a complex script full of various tricks and logic unless I have the core routine working properly.

Offline

Board footer

Powered by FluxBB