Hi again Me,
        further to my thanks, I've had a look at your suggestions.  As it
turns out it's your last (less obfuscated) solution that I needed.  I've
attached a working example.

However, it was the more obfuscated ones I thought I understood better, but
when I try the second one (to match all) I don't get the same result as when
I use the equivalent (?) longer one.

I've commented the code with my understanding of what's happening for the
more verbose solution, but I must confess I thought the shorter version
would work too.  I've tried it and included the output.  There's no
difference whether I add the ';' after the { or not - but I didn't think it
was necessary 8-).

Am I missing something in your compact suggestions?

Here's my artificial, but working, code:-

=======start quote==========
#!/usr/bin/perl -w
use strict;
use diagnostics;
use warnings;
my @printLine   = [];
my @headingLine = ("Start      ",
                   "Started    ",
                   "Stop       ",
                   "Stopped    \n" );
my @emptyLine   = ("---------- ",
                   "---------- ",
                   "---------- ",
                   "----------\n" );
while (<DATA>)  {
my ($state, $time) = split;
        if ($state == -1) {
                print @headingLine;
                @printLine = @emptyLine;
                print @printLine;
                next;
        }
#
#     $state comes in as 0, 1, 2 or 3 - if each element from $state's value
to the last 
#      matches an "empty" element, then it's ok to plug $time in, else we
need to print
#      as much as we have on the line, "empty" it, and plug the new value in
the correct slot
#
#       if($state..3 == grep{/^----/} @printLine[$state..3]) {
        my $match = 1;                         # set to true.
        for ($state..3) {                      # see if each slot to the
right of where this
                $match &&= $printLine[$_] =~ /^-----/; # goes is "empty" ie
matches /^----/
        }                                      # if they're all empty, new
time goes 
        if ($match) {
                $printLine[$state] = "$time "; # where $state says to.
          } else {                             # otherwise print the line as
it is, clear it
                print @printLine, "\n";        # out and put the new time
where it belongs
                @printLine = @emptyLine;       # to be printed when
required.
                $printLine[$state] = "$time ";
          }
}
print @printLine, "\n";                        # yup, without some smarts,
this may print all ---s

__END__
-1
0 23:40:47.9
1 12:13:22.5
2 18:36:11.0
3 06:02:26.2
0 00:45:39.7
2 03:18:30.0
3 05:58:41.3
0 05:21:55.7
1 15:34:01.8
2 10:43:28.5
3 15:15:12.4
2 04:34:15.1
3 09:52:56.5
0 00:56:23.0
======= end quote =======

RESULTS
>>> Correct
D:\perl\scripts\DAMS\modules>rangechk.plx
Start      Started    Stop       Stopped
---------- ---------- ---------- ----------
23:40:47.9 12:13:22.5 18:36:11.0 06:02:26.2
00:45:39.7 ---------- 03:18:30.0 05:58:41.3
05:21:55.7 15:34:01.8 10:43:28.5 15:15:12.4
---------- ---------- 04:34:15.1 09:52:56.5
00:56:23.0 ---------- ---------- ----------

>>> Not so correct 
D:\perl\scripts\DAMS\modules>rangech2.plx
Start      Started    Stop       Stopped
---------- ---------- ---------- ----------
---------- ---------- ---------- ----------

00:56:23.0 15:34:01.8 04:34:15.1 09:52:56.5


Once again thanks for taking the time.

Cheers
Murray Webster


-----Original Message-----
From: Me [mailto:[EMAIL PROTECTED]]
Sent: Wednesday, 4 July 2001 16:12
To: Webster, Murray; [EMAIL PROTECTED]
Subject: Re: Match range of array elements?


>    if ($printLine[$state..3] =~ /^----/)

1. The syntax $foo[....] signifies a single element of array @foo.
The ..... bit is in scalar context and should evaluate to a *single*
*numeric* value. Hence the complaint:

    Argument "" isn't numeric in array element


2. When you use a variable that isn't defined, and you have
warnings switched on, perl will complain. For some lines of
your TEST file, $state ends up not defined, hence:

    Use of uninitialized value in pattern match (m//)

The line number for the specific lines is given in the error message.


To make matters worse:

3. When you use the X..Y syntax in a scalar context, the ..
operator is the bistable (flipflop) operator, not the range
operator.

4. The =~ operator expects a single value on the left side.


You clearly ain't doing what you want to do.

I don't know what happens earlier in your script (and given
the errors above, I ain't too confident you've gotten it right),
but to match against a range of array elements, how you
might want to try:

    if (grep { /^---/ } @printLine[$state..3]) {;

to match any, or

    if ($state..3 == grep { /^---/ } @printLine[$state..3]) {;

to match all. You should add an assert that $state is (or
evaluates to) an integer between 0 and 3. And both of
these are somewhat obfuscated coding. Perhaps:

    # to match any
    my $match = 0;
    for ($state..3) {
        $match ||= $printLine[$_] =~ /^---/
    }
    if ($match) {

or

    # to match all
    my $match = 1;
    for ($state..3) {
        $match &&= $printLine[$_] =~ /^---/
    }
    if ($match) {

would be better, though note that the latter indicates
you have matched all if $state isn't in the range 0-3.

hth.

Reply via email to