[28436] in Perl-Users-Digest

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

Perl-Users Digest, Issue: 9800 Volume: 10

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Tue Oct 3 21:05:55 2006

Date: Tue, 3 Oct 2006 18:05:07 -0700 (PDT)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)

Perl-Users Digest           Tue, 3 Oct 2006     Volume: 10 Number: 9800

Today's topics:
        FAQ 5.2 (Was: inserting lines) <jgibson@mail.arc.nasa.gov>
    Re: FAQ 5.2 (Was: inserting lines) <tadmc@augustmail.com>
    Re: FAQ 5.2 (Was: inserting lines) <tadmc@augustmail.com>
    Re: FAQ 5.2 <rvtol+news@isolution.nl>
    Re: FAQ 5.2 <jgibson@mail.arc.nasa.gov>
    Re: Perl Async .10 <toddenglish@gmail.com>
    Re: perl flawed or my fault <emschwar@pobox.com>
    Re: perl flawed or my fault <emschwar@pobox.com>
    Re: problems with regex matching - invalid ranges, quan <tadmc@augustmail.com>
    Re: Reducing dependencies when initializing Log4perl? (reading news)
    Re: Reducing dependencies when initializing Log4perl? <robb@acm.org>
    Re: Reducing dependencies when initializing Log4perl? (Randal L. Schwartz)
        Spliting values and reversing a hash mlwollman@gmail.com
    Re: Spliting values and reversing a hash <see.sig@rochester.rr.com>
    Re: Spliting values and reversing a hash <someone@example.com>
        Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)

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

Date: Tue, 03 Oct 2006 15:58:04 -0700
From: Jim Gibson <jgibson@mail.arc.nasa.gov>
Subject: FAQ 5.2 (Was: inserting lines)
Message-Id: <031020061558043174%jgibson@mail.arc.nasa.gov>


I recently complained about the lack of alternate approaches to the FAQ
"How do I change one line in a file/delete a line in a file/insert a
line in the middle of a file/append to the beginning of a file?"

The official FAQ answer is:

"Use the Tie::File module, which is included in the standard distribu-
tion since Perl 5.8.0."


I think this fundamental Perl operation deserves more approaches other
than jumping right to a module and the tie concept, which could be
difficult or confusing for beginners. 

Here is my first attempt at a more complete answer. Comments are
invited. After discussion has ensued, I shall submit the result. Note
that I am not a practitioner of Perl one-liners and so supplied some
simple examples, but I think the FAQ should be slanted towards
beginners anyway.

------%<-----------------------------------------------

You can use a Perl "one-liner" with command-line switches to modify 
a file (see perlrun). The following changes all 'bar' to 'baz'
in fileA, overwriting the file:

   perl -pi -e 's/bar/baz' fileA 

Change only line 5 and save the original file as fileA.bak:

   perl -pi'.bak' -e 's/bar/baz if $.==5' fileA

Add a line before line 3:

   perl -pi -e 'print "new line 3\n" if $.==3' fileA 

Add a line at the beginning of the file:

   perl -pi -e 'print "new line 1\n" if $.==1' fileA 

Append a line to the end of the file (use -n with print statement
instead of -p):

   perl -ni -e 'print;print "$. lines\n" if eof' fileA 

Delete all lines that contain 'd':

   perl -ni -e 'print unless /d/' fileA

You can "slurp" one or more files into an array, modify the array, 
and write the array out to a new file, specifying the file(s) on the
command-line:

   @lines = do { local $/; <> }
   # modify @lines array
   open( my $out, '>', 'fileA.new' ) or
     die("Can't create fileA.new: $!");
   print $out @lines;
   close($out) or die("Can't write file: $!");

(or use the File::Slurp module.)

If the input files are too big to read into memory, use a while loop
and process the files one line at a time:

   open( my $out, '>', 'fileA.new' ) or 
     die("Can't create new file: $!");
   # add lines to the beginning of the file
   while( <> ) {
     # modify or skip a line
     print $out @lines; # write the line
     # add more lines in the middle
   }
   # add lines to the end of the file
   close($out) or die("Can't write file: $!");

You can also use Perl's tie feature to associate a file with an array.
Changes to the array become modifications to the file. Use the 
Tie::File module, which implements this feature and has been included
in the standard distribution since Perl 5.8.0.

-- 
Jim Gibson

 Posted Via Usenet.com Premium Usenet Newsgroup Services
----------------------------------------------------------
    ** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
----------------------------------------------------------        
                http://www.usenet.com


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

Date: Tue, 3 Oct 2006 18:41:55 -0500
From: Tad McClellan <tadmc@augustmail.com>
Subject: Re: FAQ 5.2 (Was: inserting lines)
Message-Id: <slrnei5ta3.uhj.tadmc@magna.augustmail.com>

Jim Gibson <jgibson@mail.arc.nasa.gov> wrote:
> 
> I recently complained about the lack of alternate approaches to the FAQ
> "How do I change one line in a file/delete a line in a file/insert a
> line in the middle of a file/append to the beginning of a file?"
> 
> The official FAQ answer is:
> 
> "Use the Tie::File module, which is included in the standard distribu-
> tion since Perl 5.8.0."


> Here is my first attempt at a more complete answer. Comments are
> invited. 


You should probably review the answer that was there before 5.8.0
(which I liked better than what we have now).

Here is the POD from 5.6.1 for easy reference (=head2 line wrapped by me):

------------------------------------------------------
=head2 How do I change one line in a file/delete a line in a file/
       insert a line in the middle of a file/append to the beginning of a file?

Those are operations of a text editor.  Perl is not a text editor.
Perl is a programming language.  You have to decompose the problem into
low-level calls to read, write, open, close, and seek.

Although humans have an easy time thinking of a text file as being a
sequence of lines that operates much like a stack of playing cards--or
punch cards--computers usually see the text file as a sequence of bytes.
In general, there's no direct way for Perl to seek to a particular line
of a file, insert text into a file, or remove text from a file.

(There are exceptions in special circumstances.  You can add or remove
data at the very end of the file.  A sequence of bytes can be replaced
with another sequence of the same length.  The C<$DB_RECNO> array
bindings as documented in L<DB_File> also provide a direct way of
modifying a file.  Files where all lines are the same length are also
easy to alter.)

The general solution is to create a temporary copy of the text file with
the changes you want, then copy that over the original.  This assumes
no locking.

    $old = $file;
    $new = "$file.tmp.$$";
    $bak = "$file.orig";

    open(OLD, "< $old")         or die "can't open $old: $!";
    open(NEW, "> $new")         or die "can't open $new: $!";

    # Correct typos, preserving case
    while (<OLD>) {
        s/\b(p)earl\b/${1}erl/i;
        (print NEW $_)          or die "can't write to $new: $!";
    }

    close(OLD)                  or die "can't close $old: $!";
    close(NEW)                  or die "can't close $new: $!";

    rename($old, $bak)          or die "can't rename $old to $bak: $!";
    rename($new, $old)          or die "can't rename $new to $old: $!";

Perl can do this sort of thing for you automatically with the C<-i>
command-line switch or the closely-related C<$^I> variable (see
L<perlrun> for more details).  Note that
C<-i> may require a suffix on some non-Unix systems; see the
platform-specific documentation that came with your port.

    # Renumber a series of tests from the command line
    perl -pi -e 's/(^\s+test\s+)\d+/ $1 . ++$count /e' t/op/taint.t

    # form a script
    local($^I, @ARGV) = ('.orig', glob("*.c"));
    while (<>) {
        if ($. == 1) {
            print "This line should appear at the top of each file\n";
        }
        s/\b(p)earl\b/${1}erl/i;        # Correct typos, preserving case
        print;
        close ARGV if eof;              # Reset $.
    }

If you need to seek to an arbitrary line of a file that changes
infrequently, you could build up an index of byte positions of where
the line ends are in the file.  If the file is large, an index of
every tenth or hundredth line end would allow you to seek and read
fairly efficiently.  If the file is sorted, try the look.pl library
(part of the standard perl distribution).

In the unique case of deleting lines at the end of a file, you
can use tell() and truncate().  The following code snippet deletes
the last line of a file without making a copy or reading the
whole file into memory:

        open (FH, "+< $file");
        while ( <FH> ) { $addr = tell(FH) unless eof(FH) }
        truncate(FH, $addr);

Error checking is left as an exercise for the reader.
------------------------------------------------------


-- 
    Tad McClellan                          SGML consulting
    tadmc@augustmail.com                   Perl programming
    Fort Worth, Texas


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

Date: Tue, 3 Oct 2006 19:50:33 -0500
From: Tad McClellan <tadmc@augustmail.com>
Subject: Re: FAQ 5.2 (Was: inserting lines)
Message-Id: <slrnei61ap.uhj.tadmc@magna.augustmail.com>

Jim Gibson <jgibson@mail.arc.nasa.gov> wrote:
> 
> I recently complained about the lack of alternate approaches to the FAQ
> "How do I change one line in a file/delete a line in a file/insert a
> line in the middle of a file/append to the beginning of a file?"


> Here is my first attempt at a more complete answer. Comments are
> invited. 


> You can use a Perl "one-liner" with command-line switches to modify 
> a file (see perlrun). 


And you can do it in a file-based program with the $^I variable,
or with the -i command-line switch.

If you want to do it in a program file rather than as a one-liner,
then be sure to local()ize the special variables into an appropriate
scope:

   {   local @ARGV = qw/ fileA /;  # same as the one-liner below
       $^I = '.bak';
       while ( <> ) {
          s/bar/baz/;
       }
   }

> The following changes all 'bar' to 'baz'
> in fileA, overwriting the file:
> 
>    perl -pi -e 's/bar/baz' fileA 
                          ^^
                          ^^

(you are missing a slash and a 'g' modifier there.)

I would not recommend that the first example make no backup file!

I would use a backup extension on every example except for maybe
one at the very end of the answer.

And there is no need to startle the unaware with "ganged" switches, so:

   perl -p -i.bak -e ...


> Change only line 5 and save the original file as fileA.bak:
> 
>    perl -pi'.bak' -e 's/bar/baz if $.==5' fileA
             ^    ^
             ^    ^

Those quotes are not needed, so they should not be there.

It would probably be nice if Tie::File had been introduced before
the examples so that both methods could be shown side-by-side:

   $array[4] =~ s/bar/baz/;  # arrays start at zero, lines start at one


> Add a line before line 3:
> 
>    perl -pi -e 'print "new line 3\n" if $.==3' fileA 


   splice @array, 2, 0, "new line 3\n";


> Add a line at the beginning of the file:
> 
>    perl -pi -e 'print "new line 1\n" if $.==1' fileA 


   unshift @array, "new line 1\n";


> Append a line to the end of the file (use -n with print statement
> instead of -p):
> 
>    perl -ni -e 'print;print "$. lines\n" if eof' fileA 
                       ^^
                       ^^ you need a space in there

   push @array, "$. lines\n";


> Delete all lines that contain 'd':
> 
>    perl -ni -e 'print unless /d/' fileA


   @array = grep !/d/, @array;


> You can "slurp" one or more files into an array, modify the array, 
                      ^^^^^^^
                      ^^^^^^^ eh? How will you know where the file
                              boundaries are when you go to write
                              them back out? Or did you mean
                              "one or more files into arrays"?

> and write the array out to a new file, 


That's way more trouble than using Tie::File, it will do the reflecting
back to disk for you, so I don't recommend including this part.


> If the input files are too big to read into memory, use 


Tie::File.   :-)


> and process the files one line at a time:


That's the same as what was done with all of the earlier -p examples,
so this part doesn't need to be included either.


> You can also use Perl's tie feature to associate a file with an array.
> Changes to the array become modifications to the file. Use the 
> Tie::File module, which implements this feature and has been included
> in the standard distribution since Perl 5.8.0.



-- 
    Tad McClellan                          SGML consulting
    tadmc@augustmail.com                   Perl programming
    Fort Worth, Texas


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

Date: Wed, 4 Oct 2006 01:30:43 +0200
From: "Dr.Ruud" <rvtol+news@isolution.nl>
Subject: Re: FAQ 5.2
Message-Id: <efv2vh.1d0.1@news.isolution.nl>

Jim Gibson schreef:

> You can "slurp" one or more files into an array, modify the array,
> and write the array out to a new file, specifying the file(s) on the
> command-line:
>
>    @lines = do { local $/; <> }

ITYM:

     @lines = <> ;

or:

     my $text ; { local $/ ; $text = <> }

-- 
Affijn, Ruud

"Gewoon is een tijger."




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

Date: Tue, 03 Oct 2006 17:23:29 -0700
From: Jim Gibson <jgibson@mail.arc.nasa.gov>
Subject: Re: FAQ 5.2
Message-Id: <031020061723292321%jgibson@mail.arc.nasa.gov>

In article <efv2vh.1d0.1@news.isolution.nl>, Dr.Ruud
<rvtol+news@isolution.nl> wrote:

> Jim Gibson schreef:
> 
> > You can "slurp" one or more files into an array, modify the array,
> > and write the array out to a new file, specifying the file(s) on the
> > command-line:
> >
> >    @lines = do { local $/; <> }
> 
> ITYM:
> 
>      @lines = <> ;

Yes, that is what I meant. Thanks.

> 
> or:
> 
>      my $text ; { local $/ ; $text = <> }

Not that one; the idea is to get the lines into an array and modify the
array. Putting the entire file into a single scalar would be another
example, but I don't know if we need another one.

It looks like I used the term "slurp" incorrectly, as the Camel book
defines it as reading the entire file into a string, not an array.

 Posted Via Usenet.com Premium Usenet Newsgroup Services
----------------------------------------------------------
    ** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
----------------------------------------------------------        
                http://www.usenet.com


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

Date: 3 Oct 2006 17:28:36 -0700
From: "Todd English" <toddenglish@gmail.com>
Subject: Re: Perl Async .10
Message-Id: <1159921716.085494.196850@h48g2000cwc.googlegroups.com>

Thank you for the reply.

> my hunch was that your problem occurred because you're deleting items
> from the hash while iterating over it, but on second thought I'm not so
> sure.

I originally thought this as well, and had tried a couple of variants
to the code I posted where I didn't mess with the proc hash until all
procs had reported their return. But this didn't make any difference
and upon further reflection I didn't think this was the case.

> anyway, I changed up your script a bit (no more deleting) and it seems
> to run ok for me.  give it a try.

I tried your example code 10 times on three different machines and I
don't see any difference between your output and mine. For example I
just ra the example and received:
Host gray:
Host x.x.x.x:   x.x.x.x result
Host y.y.y.y:   y.y.y.y result
Host maroon:
Host white:
Host goldenrod:
Host rh4as:
Host mambo:
Host brown:
Host green:     green result

I'm wondering if this is environmental. Are you on a windows machine,
or a UNIX like machine? What version of perl are you using?

Thanks for the help,
Todd English



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

Date: 03 Oct 2006 13:38:35 -0600
From: Eric Schwartz <emschwar@pobox.com>
Subject: Re: perl flawed or my fault
Message-Id: <87odst5gw4.fsf@localhost.localdomain>

"John W. Krahn" <someone@example.com> writes:
> Eric Schwartz wrote:
> > Or better yet, write it out:
> > 
> > if (defined($something)) {
> >    $note_whome = $something;
> > } else {
> >    $otherthing = 'singapore';
> > }
> 
> Or better yet, don't use "cuddled else".   :-)
> 
> perldoc perlstyle

Feh.  I like it that way; perlstyle can go hang.  I think it's
ugly. (Unless, of course, it's house style, in which case I follow
house style.)

-=Eric


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

Date: 03 Oct 2006 13:47:32 -0600
From: Eric Schwartz <emschwar@pobox.com>
Subject: Re: perl flawed or my fault
Message-Id: <87k63h5gh7.fsf@localhost.localdomain>

anno4000@radom.zrz.tu-berlin.de writes:
> I am of a split mind about using ?: in lvalue context.  It *is*
> kind of obscure, but there are situations that simply call for
> it.  One is the loop of a binary search, for example
> 
>     while ( $low < $high - 1 ) {
>         my $mid = ($low + $high)/2;
>         $list->[ $mid] le $targ ? $low : $high = $mid;
>     }
> 
> The if-else equivalent to ?: is four lines, even cuddling the else.
> I can never bring myself to use it.

I don't object to that so much, but I'd still use the if-else
equivalent (and cuddle the else too!  Bwahahahah!) just because I
think it's more readable.

-=Eric


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

Date: Tue, 3 Oct 2006 19:53:36 -0500
From: Tad McClellan <tadmc@augustmail.com>
Subject: Re: problems with regex matching - invalid ranges, quantifier follows nothing, etc.
Message-Id: <slrnei61gg.uhj.tadmc@magna.augustmail.com>

Mumia W. (reading news) <paduille.4058.mumia.w@earthlink.net> wrote:
> On 10/03/2006 09:33 AM, Jack wrote:

>>     if ($target[$i] =~ m/$temparray2[0]/i) {  print " match "; }
                                           ^
                                           ^

> if (index($target[$i],$temparray2[0]) >= 0) { print " match "; }


   if (index(lc $target[$i], lc $temparray2[0]) >= 0) { print " match "; }


(which could become painful in a big loop...)


-- 
    Tad McClellan                          SGML consulting
    tadmc@augustmail.com                   Perl programming
    Fort Worth, Texas


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

Date: Tue, 03 Oct 2006 22:10:27 GMT
From: "Mumia W. (reading news)" <paduille.4058.mumia.w@earthlink.net>
Subject: Re: Reducing dependencies when initializing Log4perl?
Message-Id: <ndBUg.9593$UG4.3285@newsread2.news.pas.earthlink.net>

On 10/03/2006 04:02 PM, robb@acm.org wrote:
> Hi,
> 
> My goal is to have zero dependencies in my source code to artifacts
> such as configuration file locations or package names.  Usually, the
> init code for Log4perl looks like this:
> 
> use Log::Log4perl;
> Log::Log4perl->init("/path/to/log.conf");
> my $logger = Log::Log4perl->get_logger("MyPackage::MySubPackage");
> 
> That's just way too much redundant information to put in the top of
> each of my source files.
> 
> Does anyone have any other solutions?  In other words, I believe one
> ought to be able to do this:
> 
> use MyLogWrapper;
> my $logger = MyLogWrapper->get_logger();
> 
> Two things would happen here:
> 1. MyLogWrapper is the only class that knows where the config file is,
> and
> 2. It is able to determine the class/package name for when it invokes
> Log4perl->get_logger.
> 
> Another option occurred to me, though for #2: I've found that if
> Log4perl->get_logger() is invoked without a param, it will determine
> the package of the caller.  But if this invocation is in a helper class
> like this, the helper class's info will be used, not the actual client.
> 
> Which made me wonder if late binding would work.  In this case, my
> wrapper would be used like this:
> 
> use MyLogWrapper;
> my $logger = MyLogWrapper->get_logger()();
> 
> Anyone following me?
> 

Yes, I think so:

package MyLogWrapper;
use strict;
use warnings;
use LogForPerl; # Placeholder for Log::Log4perl

BEGIN {
     LogForPerl->init('/path/to/log.conf');
}

sub get_logger {
     LogForPerl->get_logger('MyPackage::MySubPackage');
}

__END__

Or you could use inheritance and override 'init' and 'get_logger.'


HTH

-- 
paduille.4058.mumia.w@earthlink.net
Posting Guidelines for comp.lang.perl.misc:
http://www.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html


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

Date: 3 Oct 2006 17:20:57 -0700
From: "robb@acm.org" <robb@acm.org>
Subject: Re: Reducing dependencies when initializing Log4perl?
Message-Id: <1159921257.410341.304370@i3g2000cwc.googlegroups.com>


Mumia W. (reading news) wrote:
> package MyLogWrapper;
> use strict;
> use warnings;
> use LogForPerl; # Placeholder for Log::Log4perl
>
> BEGIN {
>      LogForPerl->init('/path/to/log.conf');
> }
>
> sub get_logger {
>      LogForPerl->get_logger('MyPackage::MySubPackage');
> }
>
> __END__
>

But the point is that it should be usable from many packages.  And, I
don't want to have code inside a package which hardcodes the package
name...  So what I'm looking for, I guess, is code to fill this blank:

sub get_logger {
     my $package_name = ... #Code to determine package of caller
     LogForPerl->get_logger($package_name);
}



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

Date: 03 Oct 2006 17:47:38 -0700
From: merlyn@stonehenge.com (Randal L. Schwartz)
To: "robb@acm.org" <robb@acm.org>
Subject: Re: Reducing dependencies when initializing Log4perl?
Message-Id: <86u02koqj9.fsf@blue.stonehenge.com>

>>>>> "robb@acm" == robb@acm org <robb@acm.org> writes:

robb@acm> 2. It is able to determine the class/package name for when it invokes Log4perl-> get_logger.

See "perldoc -f caller".

-- 
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!

-- 
Posted via a free Usenet account from http://www.teranews.com



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

Date: 3 Oct 2006 17:18:42 -0700
From: mlwollman@gmail.com
Subject: Spliting values and reversing a hash
Message-Id: <1159921122.539424.242090@b28g2000cwb.googlegroups.com>

Hello all,

I'm very, very new to Perl, and I have a question I can't quite find
the answer in the O'Reilly Perl books (Learning, Programming, and
Cookbook). Any assistance would be helpful.

I have a hash with key value pairs like:
    1 => Chocolate,Vanilla,Rocky Road
    2 => Strawberry,Vanilla, Pistachio
    3 => Cookie Dough,Chocolate
    4 => Strawberry,Pistachio

And I need to transform it to:
   Chocolate => 1,3
   Vanilla => 1,2
   Rocky Road => 1
   Strawberry => 2,4
   Pistachio =>2,4
   Cookie Dough => 3

What's a good, simple way to do that?

I thought about using while each and changing the value to an array and
foreach array element make a new has with the array element as a key
and the old key join() any existing values, I think. I'm pretty
confused now.

Thank You,
Matt



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

Date: Wed, 04 Oct 2006 00:58:29 GMT
From: Bob Walton <see.sig@rochester.rr.com>
Subject: Re: Spliting values and reversing a hash
Message-Id: <VGDUg.3011$484.843@twister.nyroc.rr.com>

mlwollman@gmail.com wrote:
 ...
> I have a hash with key value pairs like:
>     1 => Chocolate,Vanilla,Rocky Road
>     2 => Strawberry,Vanilla, Pistachio
>     3 => Cookie Dough,Chocolate
>     4 => Strawberry,Pistachio
> 
> And I need to transform it to:
>    Chocolate => 1,3
>    Vanilla => 1,2
>    Rocky Road => 1
>    Strawberry => 2,4
>    Pistachio =>2,4
>    Cookie Dough => 3
> 
> What's a good, simple way to do that?
> 
> I thought about using while each and changing the value to an array and
> foreach array element make a new has with the array element as a key
> and the old key join() any existing values, I think. I'm pretty
> confused now.
 ...
> Matt
> 

Here is one way, which is pretty much what you described, except I 
elected to use strings rather than arrays since I think you said you 
wanted strings:

use warnings;
use strict;
use Data::Dumper;
my %h; #original hash
$h{1}='Chocolate,Vanilla,Rocky Road';
$h{2}='Strawberry,Vanilla,Pistachio';
$h{3}='Cookie Dough,Chocolate';
$h{4}='Strawberry,Pistachio';
my %h1; #flavors hash
for(sort keys %h){
   my @v=split /,/,$h{$_}; #separate flavors
   for my $v(@v){
     $h1{$v}.="$_,"; #add number to flavor
   }
}
for(keys %h1){
   $h1{$_}=~s/,$//; #get rid of trailing commas
}
print Dumper(\%h1);

-- 
Bob Walton
Email: http://bwalton.com/cgi-bin/emailbob.pl


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

Date: Wed, 04 Oct 2006 01:04:52 GMT
From: "John W. Krahn" <someone@example.com>
Subject: Re: Spliting values and reversing a hash
Message-Id: <UMDUg.1476$H7.107@edtnps82>

mlwollman@gmail.com wrote:
> 
> I'm very, very new to Perl, and I have a question I can't quite find
> the answer in the O'Reilly Perl books (Learning, Programming, and
> Cookbook). Any assistance would be helpful.
> 
> I have a hash with key value pairs like:
>     1 => Chocolate,Vanilla,Rocky Road
>     2 => Strawberry,Vanilla, Pistachio
>     3 => Cookie Dough,Chocolate
>     4 => Strawberry,Pistachio
> 
> And I need to transform it to:
>    Chocolate => 1,3
>    Vanilla => 1,2
>    Rocky Road => 1
>    Strawberry => 2,4
>    Pistachio =>2,4
>    Cookie Dough => 3
> 
> What's a good, simple way to do that?

$ perl -le'
use Data::Dumper;

my %hash = (
    1 => [ "Chocolate", "Vanilla", "Rocky Road" ],
    2 => [ "Strawberry", "Vanilla", "Pistachio" ],
    3 => [ "Cookie Dough", "Chocolate" ],
    4 => [ "Strawberry", "Pistachio" ],
    );

print Dumper \%hash;

for my $key ( keys %hash ) {
    for my $flavour ( @{ delete $hash{ $key } } ) {
        push @{ $hash{ $flavour } }, $key;
        }
    }

print Dumper \%hash;
'
$VAR1 = {
          '4' => [
                   'Strawberry',
                   'Pistachio'
                 ],
          '1' => [
                   'Chocolate',
                   'Vanilla',
                   'Rocky Road'
                 ],
          '3' => [
                   'Cookie Dough',
                   'Chocolate'
                 ],
          '2' => [
                   'Strawberry',
                   'Vanilla',
                   'Pistachio'
                 ]
        };

$VAR1 = {
          'Chocolate' => [
                           '1',
                           '3'
                         ],
          'Cookie Dough' => [
                              '3'
                            ],
          'Strawberry' => [
                            '4',
                            '2'
                          ],
          'Rocky Road' => [
                            '1'
                          ],
          'Pistachio' => [
                           '4',
                           '2'
                         ],
          'Vanilla' => [
                         '1',
                         '2'
                       ]
        };



John
-- 
Perl isn't a toolbox, but a small machine shop where you can special-order
certain sorts of tools at low cost and in short order.       -- Larry Wall


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

Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin) 
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>


Administrivia:

#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.  

NOTE: due to the current flood of worm email banging on ruby, the smtp
server on ruby has been shut off until further notice. 

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.

#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 V10 Issue 9800
***************************************


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