Newbie's easy question/answer - I hope

E

evillen

Why does the following code:

------
$ixf=0;

while($ixf<33)
{
if($ixf =~ (/0|8|14|23/)){print "My \$ixf is $ixf<br>";}
$ixf++;
}
-----

produce this:

My $ixf is 0
My $ixf is 8
My $ixf is 10
My $ixf is 14
My $ixf is 18
My $ixf is 20
My $ixf is 23
My $ixf is 28
My $ixf is 30

I expected only 0, 8, 14 or 23?

Thanks
 
D

David Squire

Why does the following code:

------
$ixf=0;

while($ixf<33)
{
if($ixf =~ (/0|8|14|23/)){print "My \$ixf is $ixf<br>";}
$ixf++;
}
-----

produce this:

My $ixf is 0
My $ixf is 8
My $ixf is 10
My $ixf is 14
My $ixf is 18
My $ixf is 20
My $ixf is 23
My $ixf is 28
My $ixf is 30

I expected only 0, 8, 14 or 23?

....because you have not anchored the beginnings and ends of your match
patters. All the matches shown above contain the characters 0, 8, 14 or
23 *somewhere* in the string.

To get the result you want, you would need:

----

#!/usr/bin/perl

use strict;
use warnings;


for (0..32) {
print "Match for $_\n" if /^0$|^8$|^14$|^23$/;
}

----

Output:

Match for 0
Match for 8
Match for 14
Match for 23

----

Note also the more Perlish way of doing the loop and the conditional :)
Also I have not assumed HTML output.


DS
 
J

Jürgen Exner

Why does the following code:

------
$ixf=0;

while($ixf<33)
{
if($ixf =~ (/0|8|14|23/)){print "My \$ixf is $ixf<br>";}
$ixf++;
}
-----

produce this:

My $ixf is 0
My $ixf is 8
My $ixf is 10
My $ixf is 14
My $ixf is 18
My $ixf is 20
My $ixf is 23
My $ixf is 28
My $ixf is 30

I expected only 0, 8, 14 or 23?

Because e.g. 10 contains a 0, 18 contains an 8, and 30 contains a 0, too.
And those are the alternatives you are matching.

jue
 
E

evillen

Many thanks David

David said:
...because you have not anchored the beginnings and ends of your match
patters. All the matches shown above contain the characters 0, 8, 14 or
23 *somewhere* in the string.

To get the result you want, you would need:

----

#!/usr/bin/perl

use strict;
use warnings;


for (0..32) {
print "Match for $_\n" if /^0$|^8$|^14$|^23$/;
}

----

Output:

Match for 0
Match for 8
Match for 14
Match for 23

----

Note also the more Perlish way of doing the loop and the conditional :)
Also I have not assumed HTML output.


DS
 
E

evillen

I suspected this but why didn't '4' match?

Jürgen Exner said:
Because e.g. 10 contains a 0, 18 contains an 8, and 30 contains a 0, too.
And those are the alternatives you are matching.

jue
 
J

Jürgen Exner

I suspected this but why didn't '4' match?

Because your pattern is asking for a match against '14'. The text '14' is
not a substring of '4'.

jue
 
E

evillen

Jürgen Exner said:
Because your pattern is asking for a match against '14'. The text '14' is
not a substring of '4'.
Right - I realised that as soon as I posted... thanks
 
M

Mark Clements

David said:
...because you have not anchored the beginnings and ends of your match
patters. All the matches shown above contain the characters 0, 8, 14 or
23 *somewhere* in the string.

To get the result you want, you would need:

----

#!/usr/bin/perl

use strict;
use warnings;


for (0..32) {
print "Match for $_\n" if /^0$|^8$|^14$|^23$/;
}

/^(0|8|14|23)$/

is a little easier on the eye.
 
D

David Squire

David said:
Why does the following code:

------
$ixf=0;

while($ixf<33)
{
if($ixf =~ (/0|8|14|23/)){print "My \$ixf is $ixf<br>";}
$ixf++;
}
-----
[snip]
I expected only 0, 8, 14 or 23?

...because you have not anchored the beginnings and ends of your match
patters. All the matches shown above contain the characters 0, 8, 14 or
23 *somewhere* in the string.

To get the result you want, you would need:

----

#!/usr/bin/perl

use strict;
use warnings;


for (0..32) {
print "Match for $_\n" if /^0$|^8$|^14$|^23$/;
}

----

.... and given that you seem really to be testing for numerical equality
here, the version below is probably clearer, and quite possibly faster:

----

#!/usr/bin/perl

use strict;
use warnings;

my @good_numbers = (0, 8, 14, 23);
for my $i (0..32) {
$_ == $i and print "Match for $i\n" and last for @good_numbers;
}
 
D

DJ Stunks

David said:
given that you seem really to be testing for numerical equality
here, the version below is probably clearer, and quite possibly faster:

----

#!/usr/bin/perl

use strict;
use warnings;

my @good_numbers = (0, 8, 14, 23);
for my $i (0..32) {
$_ == $i and print "Match for $i\n" and last for @good_numbers;
}

----

arrays are not suited for existence tests. to truly speedup, use a
hash.

my %good_numbers = map { $_ => 1 } (0, 8, 14, 23);

for my $i ( 0..32 ) {
print "Match for $i\n" if $good_numbers{$i};
}

-jp
 
A

anno4000

DJ Stunks said:
arrays are not suited for existence tests.

Actually they are if the keys are small integers.
to truly speedup, use a
hash.

my %good_numbers = map { $_ => 1 } (0, 8, 14, 23);

for my $i ( 0..32 ) {
print "Match for $i\n" if $good_numbers{$i};
}

An existence test in a stricter sense would not even use the
hash values:

my %good_numbers;@good_numbers{ 0, 8, 14, 23} = ();

for my $i ( 0..32 ) {
print "Match for $i\n" if exists $good_numbers{$i};
}

This version translates directly to arrays:

my @good_numbers;
@good_numbers[ 0, 8, 14, 23] = ();

for my $i ( 0..32 ) {
print "Match for $i\n" if exists $good_numbers{$i};
}


It's a bit unusual to store the good numbers in what looks like
an array of 24 undefs, but the information is all there. It
wasn't always so, but at some version or other Perl began to
understand exists() for arrays as well as for hashes.

Anno
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,733
Messages
2,569,439
Members
44,829
Latest member
PIXThurman

Latest Threads

Top