[11367] in Perl-Users-Digest

home help back first fref pref prev next nref lref last post

Perl-Users Digest, Issue: 4967 Volume: 8

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Fri Feb 26 11:27:25 1999

Date: Fri, 26 Feb 99 08:20:55 -0800
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)

Perl-Users Digest           Fri, 26 Feb 1999     Volume: 8 Number: 4967

Today's topics:
        FAQ 4.28: How can I split a [character] delimited strin <perlfaq-suggestions@perl.com>
        FAQ 4.29: How do I strip blank space from the beginning <perlfaq-suggestions@perl.com>
    Re: FAQ 4.29: How do I strip blank space from the begin <trevor@bunny.demon.co.uk>
    Re: FAQ 4.29: How do I strip blank space from the begin <tchrist@mox.perl.com>
    Re: FAQ 4.29: How do I strip blank space from the begin <jklein@alerts.co.il>
        FAQ 4.30: How do I pad a string with blanks or pad a nu <perlfaq-suggestions@perl.com>
        FAQ 4.31: How do I extract selected columns from a stri <perlfaq-suggestions@perl.com>
        FAQ 4.32: How do I find the soundex value of a string?  <perlfaq-suggestions@perl.com>
        FAQ 4.33: How can I expand variables in text strings?   <perlfaq-suggestions@perl.com>
        FAQ 4.34: What's wrong with always quoting "$vars"?   <perlfaq-suggestions@perl.com>
        FAQ 4.35: Why don't my E<lt>E<lt>HERE documents work?   <perlfaq-suggestions@perl.com>
        FAQ 4.36: What is the difference between a list and an  <perlfaq-suggestions@perl.com>
    Re: FAQ 4.36: What is the difference between a list and (Leo Schalkwyk)
    Re: FAQ 4.36: What is the difference between a list and <tchrist@mox.perl.com>
        FAQ 4.37: What is the difference between $array[1] and  <perlfaq-suggestions@perl.com>
        FAQ 4.38: How can I extract just the unique elements of <perlfaq-suggestions@perl.com>
        FAQ 4.39: How can I tell whether a list or array contai <perlfaq-suggestions@perl.com>
        FAQ 4.40: How do I compute the difference of two arrays <perlfaq-suggestions@perl.com>
        FAQ 4.41: How do I test whether two arrays or hashes ar <perlfaq-suggestions@perl.com>
        FAQ 4.42: How do I find the first array element for whi <perlfaq-suggestions@perl.com>
        FAQ 4.43: How do I handle linked lists?   <perlfaq-suggestions@perl.com>
        FAQ 4.44: How do I handle circular lists?   <perlfaq-suggestions@perl.com>
        FAQ 4.45: How do I shuffle an array randomly?   <perlfaq-suggestions@perl.com>
        Special: Digest Administrivia (Last modified: 12 Dec 98 (Perl-Users-Digest Admin)

----------------------------------------------------------------------

Date: 21 Feb 1999 15:39:11 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.28: How can I split a [character] delimited string except when inside [character]? (Comma-separated files)  
Message-Id: <36d08b0f@csnews>

(This excerpt from perlfaq4 - Data Manipulation 
    ($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every 
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)

  How can I split a [character] delimited string except when inside
[character]? (Comma-separated files)

    Take the example case of trying to split a string that is comma-
    separated into its different fields. (We'll pretend you said comma-
    separated, not comma-delimited, which is different and almost never what
    you mean.) You can't use `split(/,/)' because you shouldn't split if the
    comma is inside quotes. For example, take a data line like this:

        SAR001,"","Cimetrix, Inc","Bob Smith","CAM",N,8,1,0,7,"Error, Core Dumped"

    Due to the restriction of the quotes, this is a fairly complex problem.
    Thankfully, we have Jeffrey Friedl, author of a highly recommended book
    on regular expressions, to handle these for us. He suggests (assuming
    your string is contained in $text):

         @new = ();
         push(@new, $+) while $text =~ m{
             "([^\"\\]*(?:\\.[^\"\\]*)*)",?  # groups the phrase inside the quotes
           | ([^,]+),?
           | ,
         }gx;
         push(@new, undef) if substr($text,-1,1) eq ',';

    If you want to represent quotation marks inside a quotation-mark-
    delimited field, escape them with backslashes (eg, `"like \"this\""'.
    Unescaping them is a task addressed earlier in this section.

    Alternatively, the Text::ParseWords module (part of the standard perl
    distribution) lets you say:

        use Text::ParseWords;
        @new = quotewords(",", 0, $text);

    There's also a Text::CSV module on CPAN.

-- 
    If I allowed "next $label" then I'd also have to allow "goto $label",
    and I don't think you really want that...  :-) [now works in perl5!]
            --Larry Wall in <1991Mar11.230002.27271@jpl-devvax.jpl.nasa.gov>


------------------------------

Date: 21 Feb 1999 16:39:13 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.29: How do I strip blank space from the beginning/end of a string?  
Message-Id: <36d09921@csnews>

(This excerpt from perlfaq4 - Data Manipulation 
    ($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every 
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)

  How do I strip blank space from the beginning/end of a string?

    Although the simplest approach would seem to be:

        $string =~ s/^\s*(.*?)\s*$/$1/;

    This is unnecessarily slow, destructive, and fails with embedded
    newlines. It is much better faster to do this in two steps:

        $string =~ s/^\s+//;
        $string =~ s/\s+$//;

    Or more nicely written as:

        for ($string) {
            s/^\s+//;
            s/\s+$//;
        }

    This idiom takes advantage of the `foreach' loop's aliasing behavior to
    factor out common code. You can do this on several strings at once, or
    arrays, or even the values of a hash if you use a slide:

        # trim whitespace in the scalar, the array, 
        # and all the values in the hash
        foreach ($scalar, @array, @hash{keys %hash}) {
            s/^\s+//;
            s/\s+$//;
        }

-- 
    "All things are proceeding rapidly to their contusion." --Larry Wall


------------------------------

Date: Tue, 23 Feb 1999 12:22:48 -0000
From: "Trevor Squires" <trevor@bunny.demon.co.uk>
Subject: Re: FAQ 4.29: How do I strip blank space from the beginning/end of a string?
Message-Id: <919772517.17004.0.nnrp-11.9e9838e3@news.demon.co.uk>

I've been going thru all of the FAQ postings to re-familiarise myself with
perl.  Something in this one struck me as odd - see below

Tom Christiansen wrote in message <36d09921@csnews>...
>(This excerpt from perlfaq4 - Data Manipulation
>    ($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)

>part of the standard set of documentation included with every

<SNIP>

>        # trim whitespace in the scalar, the array,
>        # and all the values in the hash
>        foreach ($scalar, @array, @hash{keys %hash}) {

^^^^^^^^^^^^^^^^^^^^^^^^^^^
a - what does that mean in english?  I've never seen curlies used like that.
b - why not just do: foreach ($scalar, @array, values %hash) ?

Thanks loads,
Trevor




------------------------------

Date: 23 Feb 1999 07:04:18 -0700
From: Tom Christiansen <tchrist@mox.perl.com>
Subject: Re: FAQ 4.29: How do I strip blank space from the beginning/end of a string?
Message-Id: <36d2b562@csnews>

 [courtesy cc of this posting sent to cited author via email]

In comp.lang.perl.misc, "Trevor Squires" <trevor@bunny.demon.co.uk> writes:

:I've been going thru all of the FAQ postings to re-familiarise myself with
:perl.  

Hurray!  It's amazing how many people who just haven't read it, or else
haven't read it in forever.  I have been getting no end of thank-yous
for doing this.  People want to see things in small chunks.

:Something in this one struck me as odd - see below

:>        foreach ($scalar, @array, @hash{keys %hash}) {

:a - what does that mean in english?  I've never seen curlies used like that.
:b - why not just do: foreach ($scalar, @array, values %hash) ?

>From an ultra-recent updated to perlfunc's entry on values():

    Note that you cannot modify the values of a hash this way, because
    the returned list is just a copy.  You need to use a hash slice for
    that, since it's lvaluable in a way that values() is not.

	for (values %hash)      { s/foo/bar/g }   # FAILS!
	for (@hash{keys %hash}) { s/foo/bar/g }   # ok


--tom
-- 
    "A good messenger expects to get shot." --Larry Wall


------------------------------

Date: Tue, 23 Feb 1999 16:52:48 +0200
From: Yossi Klein <jklein@alerts.co.il>
To: Trevor Squires <trevor@bunny.demon.co.uk>
Subject: Re: FAQ 4.29: How do I strip blank space from the beginning/end of a string?
Message-Id: <Pine.SO4.4.10.9902231642180.2213-100000@cain.alerts.co.il>

When doing a foreach, the index variable 'magically' becomes the variable
that it is currently referring to:

For instance, if $a = 'abc'

and you do

foreach $idx ($a)
{
   $idx =~ s/a//;
}

then $a will now be 'bc'. (Obviously, this also works for the default
index variable of the foreach() a.k.a. $_ - I just put in $idx for
clarity).

If you do a foreach (values %abc), then $_ becomes an 'alias' for each
element of the anonymous list returned by values(). The actual elements of
%abc won't be changed.

If, however, you do foreach (@abc{keys %abc}), $_ actually becomes the
value of each element of the hash, and modifying $_ will modify the
elements in %abc.

I hope this makes sense.

Yossi Klein
News Alert Inc.

On Tue, 23 Feb 1999, Trevor Squires wrote:

> I've been going thru all of the FAQ postings to re-familiarise myself with
> perl.  Something in this one struck me as odd - see below
> 
> Tom Christiansen wrote in message <36d09921@csnews>...
> >(This excerpt from perlfaq4 - Data Manipulation
> >    ($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
> 
> >part of the standard set of documentation included with every
> 
> <SNIP>
> 
> >        # trim whitespace in the scalar, the array,
> >        # and all the values in the hash
> >        foreach ($scalar, @array, @hash{keys %hash}) {
> 
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^
> a - what does that mean in english?  I've never seen curlies used like that.
> b - why not just do: foreach ($scalar, @array, values %hash) ?
> 
> Thanks loads,
> Trevor
> 
> 
> 
> 



------------------------------

Date: 21 Feb 1999 17:39:15 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.30: How do I pad a string with blanks or pad a number with zeroes?  
Message-Id: <36d0a733@csnews>

(This excerpt from perlfaq4 - Data Manipulation 
    ($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every 
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)

  How do I pad a string with blanks or pad a number with zeroes?

    (This answer contributed by Uri Guttman)

    In the following examples, `$pad_len' is the length to which you wish to
    pad the string, `$text' or `$num' contains the string to be padded, and
    `$pad_char' contains the padding character. You can use a single
    character string constant instead of the `$pad_char' variable if you
    know what it is in advance.

    The simplest method use the `sprintf' function. It can pad on the left
    or right with blanks and on the left with zeroes.

        # Left padding with blank:
        $padded = sprintf( "%${pad_len}s", $text ) ;

        # Right padding with blank:
        $padded = sprintf( "%${pad_len}s", $text ) ;

        # Left padding with 0:
        $padded = sprintf( "%0${pad_len}d", $num ) ;

    If you need to pad with a character other than blank or zero you can use
    one of the following methods.

    These methods generate a pad string with the `x' operator and
    concatenate that with the original text.

    Left and right padding with any character:

        $padded = $pad_char x ( $pad_len - length( $text ) ) . $text ;
        $padded = $text . $pad_char x ( $pad_len - length( $text ) ) ;

    Or you can left or right pad $text directly:

        $text .= $pad_char x ( $pad_len - length( $text ) ) ;
        substr( $text, 0, 0 ) = $pad_char x ( $pad_len - length( $text ) ) ;

-- 
"SPARC" is "CRAPS" backwards --Rob Pike


------------------------------

Date: 21 Feb 1999 18:39:17 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.31: How do I extract selected columns from a string?  
Message-Id: <36d0b545@csnews>

(This excerpt from perlfaq4 - Data Manipulation 
    ($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every 
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)

  How do I extract selected columns from a string?

    Use substr() or unpack(), both documented in the perlfunc manpage. If
    you prefer thinking in terms of columns instead of widths, you can use
    this kind of thing:

        # determine the unpack format needed to split Linux ps output
        # arguments are cut columns
        my $fmt = cut2fmt(8, 14, 20, 26, 30, 34, 41, 47, 59, 63, 67, 72);

        sub cut2fmt { 
            my(@positions) = @_;
            my $template  = '';
            my $lastpos   = 1;
            for my $place (@positions) {
                $template .= "A" . ($place - $lastpos) . " "; 
                $lastpos   = $place;
            }
            $template .= "A*";
            return $template;
        }

-- 
    X-Windows: The problem for your problem.
	--Jamie Zawinski


------------------------------

Date: 21 Feb 1999 19:39:20 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.32: How do I find the soundex value of a string?  
Message-Id: <36d0c358@csnews>

(This excerpt from perlfaq4 - Data Manipulation 
    ($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every 
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)

  How do I find the soundex value of a string?

    Use the standard Text::Soundex module distributed with perl.

-- 
if (*name == '+' && len > 1 && name[len-1] != '|') {  /* scary */
    --Larry Wall, from doio.c in the v5.0 perl distribution 


------------------------------

Date: 21 Feb 1999 20:39:22 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.33: How can I expand variables in text strings?  
Message-Id: <36d0d16a@csnews>

(This excerpt from perlfaq4 - Data Manipulation 
    ($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every 
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)

  How can I expand variables in text strings?

    Let's assume that you have a string like:

        $text = 'this has a $foo in it and a $bar';

    If those were both global variables, then this would suffice:

        $text =~ s/\$(\w+)/${$1}/g;  # no /e needed

    But since they are probably lexicals, or at least, they could be, you'd
    have to do this:

        $text =~ s/(\$\w+)/$1/eeg;
        die if $@;                  # needed /ee, not /e

    It's probably better in the general case to treat those variables as
    entries in some special hash. For example:

        %user_defs = ( 
            foo  => 23,
            bar  => 19,
        );
        $text =~ s/\$(\w+)/$user_defs{$1}/g;

    See also ``How do I expand function calls in a string?'' in this section
    of the FAQ.

-- 
Perl has grown from being a very good scripting language into something
like a cross between a universal solvent and an open-ended Mandarin
where new ideograms are invented hourly.  --Jeffrey Davis


------------------------------

Date: 21 Feb 1999 21:39:24 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.34: What's wrong with always quoting "$vars"?  
Message-Id: <36d0df7c@csnews>

(This excerpt from perlfaq4 - Data Manipulation 
    ($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every 
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)

  What's wrong with always quoting "$vars"?

    The problem is that those double-quotes force stringification, coercing
    numbers and references into strings, even when you don't want them to
    be. Think of it this way: double-quote expansion is used to produce new
    strings. If you already have a string, why do you need more?

    If you get used to writing odd things like these:

        print "$var";       # BAD
        $new = "$old";      # BAD
        somefunc("$var");   # BAD

    You'll be in trouble. Those should (in 99.8% of the cases) be the
    simpler and more direct:

        print $var;
        $new = $old;
        somefunc($var);

    Otherwise, besides slowing you down, you're going to break code when the
    thing in the scalar is actually neither a string nor a number, but a
    reference:

        func(\@array);
        sub func {
            my $aref = shift;
            my $oref = "$aref";  # WRONG
        }

    You can also get into subtle problems on those few operations in Perl
    that actually do care about the difference between a string and a
    number, such as the magical `++' autoincrement operator or the syscall()
    function.

    Stringification also destroys arrays.

        @lines = `command`;
        print "@lines";             # WRONG - extra blanks
        print @lines;               # right

-- 
    It's there as a sop to former Ada programmers.  :-)
        --Larry Wall regarding 10_000_000 in <11556@jpl-devvax.JPL.NASA.GOV>


------------------------------

Date: 21 Feb 1999 22:39:27 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.35: Why don't my E<lt>E<lt>HERE documents work?  
Message-Id: <36d0ed8f@csnews>

(This excerpt from perlfaq4 - Data Manipulation 
    ($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every 
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)

  Why don't my <<HERE documents work?

    Check for these three things:

    1. There must be no space after the << part.
    2. There (probably) should be a semicolon at the end.
    3. You can't (easily) have any space in front of the tag.
    If you want to indent the text in the here document, you can do this:

        # all in one
        ($VAR = <<HERE_TARGET) =~ s/^\s+//gm;
            your text
            goes here
        HERE_TARGET

    But the HERE_TARGET must still be flush against the margin. If you want
    that indented also, you'll have to quote in the indentation.

        ($quote = <<'    FINIS') =~ s/^\s+//gm;
                ...we will have peace, when you and all your works have
                perished--and the works of your dark master to whom you
                would deliver us. You are a liar, Saruman, and a corrupter
                of men's hearts.  --Theoden in /usr/src/perl/taint.c
            FINIS
        $quote =~ s/\s*--/\n--/;

    A nice general-purpose fixer-upper function for indented here documents
    follows. It expects to be called with a here document as its argument.
    It looks to see whether each line begins with a common substring, and if
    so, strips that off. Otherwise, it takes the amount of leading white
    space found on the first line and removes that much off each subsequent
    line.

        sub fix {
            local $_ = shift;
            my ($white, $leader);  # common white space and common leading string
            if (/^\s*(?:([^\w\s]+)(\s*).*\n)(?:\s*\1\2?.*\n)+$/) {
                ($white, $leader) = ($2, quotemeta($1));
            } else {
                ($white, $leader) = (/^(\s+)/, '');
            }
            s/^\s*?$leader(?:$white)?//gm;
            return $_;
        }

    This works with leading special strings, dynamically determined:

        $remember_the_main = fix<<'    MAIN_INTERPRETER_LOOP';
            @@@ int
            @@@ runops() {
            @@@     SAVEI32(runlevel);
            @@@     runlevel++;
            @@@     while ( op = (*op->op_ppaddr)() ) ;
            @@@     TAINT_NOT;
            @@@     return 0;
            @@@ }
        MAIN_INTERPRETER_LOOP

    Or with a fixed amount of leading white space, with remaining
    indentation correctly preserved:

        $poem = fix<<EVER_ON_AND_ON;
           Now far ahead the Road has gone,
              And I must follow, if I can,
           Pursuing it with eager feet,
              Until it joins some larger way
           Where many paths and errands meet.
              And whither then? I cannot say.
                    --Bilbo in /usr/src/perl/pp_ctl.c
        EVER_ON_AND_ON

-- 
    "You need to go and find someone to teach you the rudiments of irrational
    discourse." --Larry Wall


------------------------------

Date: 21 Feb 1999 23:39:29 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.36: What is the difference between a list and an array?  
Message-Id: <36d0fba1@csnews>

(This excerpt from perlfaq4 - Data Manipulation 
    ($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every 
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)

  What is the difference between a list and an array?

    An array has a changeable length. A list does not. An array is something
    you can push or pop, while a list is a set of values. Some people make
    the distinction that a list is a value while an array is a variable.
    Subroutines are passed and return lists, you put things into list
    context, you initialize arrays with lists, and you foreach() across a
    list. `@' variables are arrays, anonymous arrays are arrays, arrays in
    scalar context behave like the number of elements in them, subroutines
    access their arguments through the array `@_', push/pop/shift only work
    on arrays.

    As a side note, there's no such thing as a list in scalar context. When
    you say

        $scalar = (2, 5, 7, 9);

    you're using the comma operator in scalar context, so it evaluates the
    left hand side, then evaluates and returns the left hand side. This
    causes the last value to be returned: 9.

-- 
    "To claim any more than that is to invite a religious war, which I ain't.
    Go thou and don't likewise."
    	--Larry Wall


------------------------------

Date: 22 Feb 1999 18:13:51 GMT
From: schalkwy@minnie.RZ-Berlin.MPG.DE (Leo Schalkwyk)
Subject: Re: FAQ 4.36: What is the difference between a list and an array?
Message-Id: <7as6ov$oga$1@fu-berlin.de>

Tom Christiansen (perlfaq-suggestions@perl.com) wrote:
: (This excerpt from perlfaq4 - Data Manipulation 

<snip>
:     you're using the comma operator in scalar context, so it evaluates the
:     left hand side, then evaluates and returns the left hand side. This
      ^^^^^                                          ^^^^^
                                                   um, right?
      
      
      
:     causes the last value to be returned: 9.

: -- 
:     "To claim any more than that is to invite a religious war, which I ain't.
:     Go thou and don't likewise."
:     	--Larry Wall

--
	 


------------------------------

Date: 22 Feb 1999 11:33:28 -0700
From: Tom Christiansen <tchrist@mox.perl.com>
Subject: Re: FAQ 4.36: What is the difference between a list and an array?
Message-Id: <36d1a2f8@csnews>

 [courtesy cc of this posting sent to cited author via email]

In comp.lang.perl.misc, schalkwy@minnie.RZ-Berlin.MPG.DE (Leo Schalkwyk) writes:
:Tom Christiansen (perlfaq-suggestions@perl.com) wrote:
::     you're using the comma operator in scalar context, so it evaluates the
::     left hand side, then evaluates and returns the left hand side. This
:      ^^^^^                                          ^^^^^
:                                                   um, right?

right.

--tom
-- 
Unix is defined by whatever is running on Dennis Ritchie's machine.


------------------------------

Date: 22 Feb 1999 00:39:31 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.37: What is the difference between $array[1] and @array[1]?  
Message-Id: <36d109b3@csnews>

(This excerpt from perlfaq4 - Data Manipulation 
    ($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every 
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)

  What is the difference between $array[1] and @array[1]?

    The former is a scalar value, the latter an array slice, which makes it
    a list with one (scalar) value. You should use $ when you want a scalar
    value (most of the time) and @ when you want a list with one scalar
    value in it (very, very rarely; nearly never, in fact).

    Sometimes it doesn't make a difference, but sometimes it does. For
    example, compare:

        $good[0] = `some program that outputs several lines`;

    with

        @bad[0]  = `same program that outputs several lines`;

    The -w flag will warn you about these matters.

-- 
If you can stick your finger in it, you can hang from it.  --Andrew Hume


------------------------------

Date: 22 Feb 1999 01:39:34 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.38: How can I extract just the unique elements of an array?  
Message-Id: <36d117c6@csnews>

(This excerpt from perlfaq4 - Data Manipulation 
    ($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every 
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)

  How can I extract just the unique elements of an array?

    There are several possible ways, depending on whether the array is
    ordered and whether you wish to preserve the ordering.

    a) If @in is sorted, and you want @out to be sorted:
    (this assumes all true values in the array)
            $prev = 'nonesuch';
            @out = grep($_ ne $prev && ($prev = $_), @in);

        This is nice in that it doesn't use much extra memory, simulating
        uniq(1)'s behavior of removing only adjacent duplicates. It's less
        nice in that it won't work with false values like undef, 0, or "";
        "0 but true" is ok, though.

    b) If you don't know whether @in is sorted:
            undef %saw;
            @out = grep(!$saw{$_}++, @in);

    c) Like (b), but @in contains only small integers:
            @out = grep(!$saw[$_]++, @in);

    d) A way to do (b) without any loops or greps:
            undef %saw;
            @saw{@in} = ();
            @out = sort keys %saw;  # remove sort if undesired

    e) Like (d), but @in contains only small positive integers:
            undef @ary;
            @ary[@in] = @in;
            @out = @ary;

    But perhaps you should have been using a hash all along, eh?

-- 
    That means I'll have to use $ans to suppress newlines now.  
    Life is ridiculous. 
        --Larry Wall in Configure from the perl distribution


------------------------------

Date: 22 Feb 1999 02:39:36 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.39: How can I tell whether a list or array contains a certain element?  
Message-Id: <36d125d8@csnews>

(This excerpt from perlfaq4 - Data Manipulation 
    ($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every 
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)

  How can I tell whether a list or array contains a certain element?

    Hearing the word "in" is an *in*dication that you probably should have
    used a hash, not a list or array, to store your data. Hashes are
    designed to answer this question quickly and efficiently. Arrays aren't.

    That being said, there are several ways to approach this. If you are
    going to make this query many times over arbitrary string values, the
    fastest way is probably to invert the original array and keep an
    associative array lying about whose keys are the first array's values.

        @blues = qw/azure cerulean teal turquoise lapis-lazuli/;
        undef %is_blue;
        for (@blues) { $is_blue{$_} = 1 }

    Now you can check whether $is_blue{$some_color}. It might have been a
    good idea to keep the blues all in a hash in the first place.

    If the values are all small integers, you could use a simple indexed
    array. This kind of an array will take up less space:

        @primes = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31);
        undef @is_tiny_prime;
        for (@primes) { $is_tiny_prime[$_] = 1; }

    Now you check whether $is_tiny_prime[$some_number].

    If the values in question are integers instead of strings, you can save
    quite a lot of space by using bit strings instead:

        @articles = ( 1..10, 150..2000, 2017 );
        undef $read;
        for (@articles) { vec($read,$_,1) = 1 }

    Now check whether `vec($read,$n,1)' is true for some `$n'.

    Please do not use

        $is_there = grep $_ eq $whatever, @array;

    or worse yet

        $is_there = grep /$whatever/, @array;

    These are slow (checks every element even if the first matches),
    inefficient (same reason), and potentially buggy (what if there are
    regexp characters in $whatever?). If you're only testing once, then use:

        $is_there = 0;
        foreach $elt (@array) {
            if ($elt eq $elt_to_find) {
                $is_there = 1;
                last;
            }
        }
        if ($is_there) { ... }

-- 
The X server has to be the biggest program I've ever seen that doesn't 
do anything for you.  --Ken Thompson


------------------------------

Date: 22 Feb 1999 03:39:44 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.40: How do I compute the difference of two arrays?  How do I compute the intersection of two arrays?  
Message-Id: <36d133f0@csnews>

(This excerpt from perlfaq4 - Data Manipulation 
    ($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every 
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)

  How do I compute the difference of two arrays?  How do I compute the intersection of two arrays?

    Use a hash. Here's code to do both and more. It assumes that each
    element is unique in a given array:

        @union = @intersection = @difference = ();
        %count = ();
        foreach $element (@array1, @array2) { $count{$element}++ }
        foreach $element (keys %count) {
            push @union, $element;
            push @{ $count{$element} > 1 ? \@intersection : \@difference }, $element;
        }

-- 
MAGIC*  xmg_magic;  /* linked list of magicalness */
    --Larry Wall, from sv.h in the v5.0 perl distribution


------------------------------

Date: 22 Feb 1999 04:39:53 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.41: How do I test whether two arrays or hashes are equal?  
Message-Id: <36d14209@csnews>

(This excerpt from perlfaq4 - Data Manipulation 
    ($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every 
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)

  How do I test whether two arrays or hashes are equal?

    The following code works for single-level arrays. It uses a stringwise
    comparison, and does not distinguish defined versus undefined empty
    strings. Modify if you have other needs.

        $are_equal = compare_arrays(\@frogs, \@toads);

        sub compare_arrays {
            my ($first, $second) = @_;
            local $^W = 0;  # silence spurious -w undef complaints
            return 0 unless @$first == @$second;
            for (my $i = 0; $i < @$first; $i++) {
                return 0 if $first->[$i] ne $second->[$i];
            }
            return 1;
        }

    For multilevel structures, you may wish to use an approach more like
    this one. It uses the CPAN module FreezeThaw:

        use FreezeThaw qw(cmpStr);
        @a = @b = ( "this", "that", [ "more", "stuff" ] );

        printf "a and b contain %s arrays\n",
            cmpStr(\@a, \@b) == 0 
                ? "the same" 
                : "different";

    This approach also works for comparing hashes. Here we'll demonstrate
    two different answers:

        use FreezeThaw qw(cmpStr cmpStrHard);

        %a = %b = ( "this" => "that", "extra" => [ "more", "stuff" ] );
        $a{EXTRA} = \%b;
        $b{EXTRA} = \%a;                    

        printf "a and b contain %s hashes\n",
            cmpStr(\%a, \%b) == 0 ? "the same" : "different";

        printf "a and b contain %s hashes\n",
            cmpStrHard(\%a, \%b) == 0 ? "the same" : "different";

    The first reports that both those the hashes contain the same data,
    while the second reports that they do not. Which you prefer is left as
    an exercise to the reader.

-- 
Remember why the good Lord made your eyes -- Pla-gi-a-rize! --Tom Lehrer


------------------------------

Date: 22 Feb 1999 05:40:01 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.42: How do I find the first array element for which a condition is true?  
Message-Id: <36d15021@csnews>

(This excerpt from perlfaq4 - Data Manipulation 
    ($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every 
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)

  How do I find the first array element for which a condition is true?

    You can use this if you care about the index:

        for ($i= 0; $i < @array; $i++) {
            if ($array[$i] eq "Waldo") {
                $found_index = $i;
                last;
            }
        }

    Now `$found_index' has what you want.

-- 
"'My country right or wrong' is like saying, 'My mother drunk or sober.'" 
 - G. K. Chesterton


------------------------------

Date: 22 Feb 1999 06:40:35 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.43: How do I handle linked lists?  
Message-Id: <36d15e53@csnews>

(This excerpt from perlfaq4 - Data Manipulation 
    ($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every 
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)

  How do I handle linked lists?

    In general, you usually don't need a linked list in Perl, since with
    regular arrays, you can push and pop or shift and unshift at either end,
    or you can use splice to add and/or remove arbitrary number of elements
    at arbitrary points. Both pop and shift are both O(1) operations on
    perl's dynamic arrays. In the absence of shifts and pops, push in
    general needs to reallocate on the order every log(N) times, and unshift
    will need to copy pointers each time.

    If you really, really wanted, you could use structures as described in
    the perldsc manpage or the perltoot manpage and do just what the
    algorithm book tells you to do. For example, imagine a list node like
    this:

        $node = {
            VALUE => 42,
            LINK  => undef,
        };

    You could walk the list this way:

        print "List: ";
        for ($node = $head;  $node; $node = $node->{LINK}) {
            print $node->{VALUE}, " ";
        }
        print "\n";

    You could grow the list this way:

        my ($head, $tail);
        $tail = append($head, 1);       # grow a new head
        for $value ( 2 .. 10 ) {
            $tail = append($tail, $value);
        }

        sub append {
            my($list, $value) = @_;
            my $node = { VALUE => $value };
            if ($list) {
                $node->{LINK} = $list->{LINK};
                $list->{LINK} = $node;
            } else {
                $_[0] = $node;      # replace caller's version
            }
            return $node;
        }

    But again, Perl's built-in are virtually always good enough.

-- 
    I already have too much problem with people thinking the efficiency of
    a perl construct is related to its length.  On the other hand, I'm
    perfectly capable of changing my mind next week...  :-) --lwall


------------------------------

Date: 22 Feb 1999 07:33:26 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.44: How do I handle circular lists?  
Message-Id: <36d16ab6@csnews>

(This excerpt from perlfaq4 - Data Manipulation 
    ($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every 
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)

  How do I handle circular lists?

    Circular lists could be handled in the traditional fashion with linked
    lists, or you could just do something like this with an array:

        unshift(@array, pop(@array));  # the last shall be first
        push(@array, shift(@array));   # and vice versa

-- 
    Emacs is a fine programming language, but I still prefer perl.


------------------------------

Date: 22 Feb 1999 08:33:36 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.45: How do I shuffle an array randomly?  
Message-Id: <36d178d0@csnews>

(This excerpt from perlfaq4 - Data Manipulation 
    ($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every 
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)

  How do I shuffle an array randomly?

    Use this:

        # fisher_yates_shuffle( \@array ) : 
        # generate a random permutation of @array in place
        sub fisher_yates_shuffle {
            my $array = shift;
            my $i;
            for ($i = @$array; --$i; ) {
                my $j = int rand ($i+1);
                next if $i == $j;
                @$array[$i,$j] = @$array[$j,$i];
            }
        }

        fisher_yates_shuffle( \@array );    # permutes @array in place

    You've probably seen shuffling algorithms that works using splice,
    randomly picking another element to swap the current element with:

        srand;
        @new = ();
        @old = 1 .. 10;  # just a demo
        while (@old) {
            push(@new, splice(@old, rand @old, 1));
        }

    This is bad because splice is already O(N), and since you do it N times,
    you just invented a quadratic algorithm; that is, O(N**2). This does not
    scale, although Perl is so efficient that you probably won't notice this
    until you have rather largish arrays.

-- 
    Perl programming is an *empirical* science!  
	    --Larry Wall in <10226@jpl-devvax.JPL.NASA.GOV>


------------------------------

Date: 12 Dec 98 21:33:47 GMT (Last modified)
From: Perl-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin) 
Subject: Special: Digest Administrivia (Last modified: 12 Dec 98)
Message-Id: <null>


Administrivia:

Well, after 6 months, here's the answer to the quiz: what do we do about
comp.lang.perl.moderated. Answer: nothing. 

]From: Russ Allbery <rra@stanford.edu>
]Date: 21 Sep 1998 19:53:43 -0700
]Subject: comp.lang.perl.moderated available via e-mail
]
]It is possible to subscribe to comp.lang.perl.moderated as a mailing list.
]To do so, send mail to majordomo@eyrie.org with "subscribe clpm" in the
]body.  Majordomo will then send you instructions on how to confirm your
]subscription.  This is provided as a general service for those people who
]cannot receive the newsgroup for whatever reason or who just prefer to
]receive messages via e-mail.

The Perl-Users Digest is a retransmission of the USENET newsgroup
comp.lang.perl.misc.  For subscription or unsubscription requests, send
the single line:

	subscribe perl-users
or:
	unsubscribe perl-users

to almanac@ruby.oce.orst.edu.  

To submit articles to comp.lang.perl.misc (and this Digest), send your
article to perl-users@ruby.oce.orst.edu.

To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.

To request back copies (available for a week or so), send your request
to almanac@ruby.oce.orst.edu with the command "send perl-users x.y",
where x is the volume number and y is the issue number.

The Meta-FAQ, an article containing information about the FAQ, is
available by requesting "send perl-users meta-faq". The real FAQ, as it
appeared last in the newsgroup, can be retrieved with the request "send
perl-users FAQ". Due to their sizes, neither the Meta-FAQ nor the FAQ
are included in the digest.

The "mini-FAQ", which is an updated version of the Meta-FAQ, is
available by requesting "send perl-users mini-faq". It appears twice
weekly in the group, but is not distributed in the digest.

For other requests pertaining to the digest, send mail to
perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
sending perl questions to the -request address, I don't have time to
answer them even if I did know the answer.


------------------------------
End of Perl-Users Digest V8 Issue 4967
**************************************

home help back first fref pref prev next nref lref last post