Perl-Sensitive Sunglasses PerlMonks

### if statement consolidation

 on Jun 27, 2012 at 15:35 UTC Need Help??
shortyfw06 has asked for the wisdom of the Perl Monks concerning the following question:

I am wondering if there's a better way to do the following. This code works as it is but it seems like a lot of numbers and variables to keep track of and I thought there may be a more consolidated way to do the same thing. The variables being assigned values are used as hash keys and array locations further along in the code. Thanks.

```                        if (\$h == 1) {
\$j=\$h+1;
\$p=0;
\$v=9;
}
if (\$h == 3) {
\$j=\$h+2;
\$p=1;
\$v=10;
}
if (\$h == 5) {
\$j=\$h+3;
\$p=0;
\$v=11;
}
if (\$h == 7) {
\$j=\$h+4;
\$p=1;
\$v=12;
}
if (\$h == 10) {
\$j=\$h+5;
\$p=0;
\$v=5;
}
if (\$h == 12) {
\$j=\$h+6;
\$p=1;
\$v=6;
}
if (\$h == 14) {
\$j=\$h+7;
\$p=0;
\$v=7;
}
if (\$h == 16) {
\$j=\$h+8;
\$p=1;
\$v=8;
}

Replies are listed 'Best First'.
Re: if statement consolidation
by moritz (Cardinal) on Jun 27, 2012 at 15:45 UTC

You can always do the data-driven approach, for example

```my %inits = (
1 => [1, 0, 9],
2 => [2, 1, 10],
3 => [3, 0, 11],
# rest of the values go here
);
if (\$inits{\$h}) {
my @i = @{ \$inits{\$h} };
\$j = \$h + \$i[0];
\$p = \$i[1];
\$v = \$i[2];
}

Or even

```my %inits = (
1 => [2, 0, 9],
2 => [5, 1, 10],
3 => [8, 0, 11],
# rest of the values go here
);
(\$i, \$p, \$v) = @{\$inits{\$h}} if \$inits{\$h};
Re: if statement consolidation
by choroba (Bishop) on Jun 27, 2012 at 15:49 UTC
I would use a hash:
```my %changes = (1 => [1, 0, 9],
3 => [2, 1, 10],
5 => [3, 0, 11],
7 => [4, 1, 12],
10 => [5, 0, 5],
12 => [6, 1, 6],
14 => [7, 0, 7],
16 => [8, 1, 8],
);

if (exists \$changes{\$h}) {
\$j = \$h + \$changes{\$h}->[0];
\$p = \$changes{\$h}->[1];
\$v = \$changes{\$h}->[2];
}
Re: if statement consolidation
by muba (Priest) on Jun 27, 2012 at 15:48 UTC

If your Perl is relatively modern, you could look into given/when. Another idea might to write a look-up hash and draw from that. I'm not saying it's the best idea, but at least it's an idea. Update: and a rather popular idea, too.

```my %values_for_h =>
1   =>  [1, 0,  9],
3   =>  [2, 1, 10],
5   =>  [3, 0, 11],
7   =>  [4, 1, 11],
10   =>  [5, 0,  5],
12   =>  [6, 1   6],
14   =>  [7, 0,  7],
16   =>  [8, 1,  8]
);

if (exists \$values_for_h{\$h}) {
\$j = \$h + \$values_for_h{\$h}->[0];
\$p = \$values_for_h{\$h}->[1];
\$v = \$values_for_h{\$h}->[2];
}
Re: if statement consolidation
by choroba (Bishop) on Jun 27, 2012 at 16:19 UTC
```if (\$h > 0 and \$h <= 16 and \$h % 2 == \$h < 9) {
my \$n = int((\$h + 1) / 2);
\$j = \$h + \$n;
\$p = 0 + ! (\$n % 2);
\$v = \$n + (8 * (\$h < 10));
}

Note that the original code did not modify any of the variables unless \$h has one of a list of certain values. If that's important behavior, there should be an if-statement guarding your code.

Re: if statement consolidation
by BrowserUk (Pope) on Jun 27, 2012 at 15:53 UTC

Use a lookup (check that I transcribed the numbers correctly):

```my %lookup = (
1, [  2, 0,  9 ],
3, [  5, 1, 10 ],
5, [  8, 0, 11 ],
7, [ 11, 1, 12 ],
10,[ 15, 0,  5 ],
12,[ 18, 1,  6 ],
14,[ 21, 0,  7 ],
16,[ 24, 1,  8 ],
);

my( \$j, \$p, \$v ) = @{ \$lookup{ \$h } };

With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

The start of some sanity?

Re: if statement consolidation
by bulk88 (Priest) on Jun 28, 2012 at 00:54 UTC
Use "data driven" as described in this thread. Or use XS, a C switch statement is orders of magnitude smaller in memory than your code, especially if all these numbers fit in the range of a char. For a pure perl solution, to reduce opcodes (nextstates and sassigns), convert a
```                            \$j=\$h+8;
\$p=1;
\$v=8;
to (one aassign op)
```(\$j, \$p, \$v) = (\$h+8, 1, 8);
or fatter but faster (no nextstates, but multiple sassign might be faster one aassign a profiler, I dont remember from last time I tried to optimize away nextstate ops)
```(\$j = \$h+8),(\$p = 1), (\$v = 8);
note, I didn't B::Concise this post.
Re: if statement consolidation
by RichardK (Parson) on Jun 27, 2012 at 18:31 UTC

If I may say, that's a pretty ugly if , IMHO ;)

So maybe that's a signal that you're going about it in the wrong way. Try restating the original problem and think of a different approach.

Re: if statement consolidation
by Anonymous Monk on Jun 27, 2012 at 20:33 UTC
There is also something to be said for clarity. The only real caution here is that you probably want to be using elsif especially if there is any chance whatsoever that the value of \$h could be modified within any of the if-blocks. Even though the code as written (with the elsif change) is wordy and repetitious, it is also easy to understand and modify, and each alternative block of code stands alone. You could, if you chose and if you needed to, do completely separate and unrelated things in each block: there is no functional correlation or "tying" of any kind between them. If that works for you, all things properly considered, then do it without remorse. it is not "wrong."
Re: if statement consolidation
by linuxkid (Sexton) on Jun 27, 2012 at 23:02 UTC

```given(\$h) {
when (2) {...}
}

# --linuxkid

imrunningoutofideas.co.cc

Create A New User
Node Status?
node history
Node Type: perlquestion [id://978701]
Approved by muba
help
Chatterbox?
 [LanX]: nah .. [LanX]: ;-)

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (8)
As of 2018-03-19 13:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
When I think of a mole I think of:

Results (240 votes). Check out past polls.

Notices?