[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

[Fun With Perl] Code rewrite



# I collected this rewrite over 6 months ago. More recently, I had reason to go
# back and look at something very similar. When I did, I posted the 
question to # comp.lang.perl.moderated.

# The answers I received seem to epitomize the essence of Fun With Perl

# Original code
   $directory = '/tmp';
   $file = '/tmp/foo';

   @lines = (
     '"a","b","/tmp","/tmp/foo","c","d","e","f","g","h","i"',
     '"z","y","/tmp","/tmp/foo","r","s","t","u","v","w","x"',
   );


    foreach $line (@lines) {
		if ($line =~
          m!"(.*)","(.*)","($directory)","($file)","(.*)","(.*)","(.*)","(.*)",
            "(.*)","(.*)","(.*)"!i)
         {
			$idnums{$i} = $i;
			$contactid{$i} = $1;
			$urls{$i} = $2;
			$states{$i} = $3;
			$regions{$i} = $4;
			$subregions{$i} = $5;
			$seealsos{$i} = $6;
			$listings{$i} = $7;
			$descriptions{$i} = $8;
			$cities{$i} = $9;
			$names{$i} = $10;
			$linkurls{$i} = $11;
             print "line: $line\n";
		    print "\$i $i\n";
			$i++;

         }
}

# Rewrite:

$i = 0;
foreach $line (@lines) {
     if ($line =~ m/".*,"$directory","$file".*$/) {

         ($contactid{$i}, $url{$i}, $state{$i}, $region{$i}, $subregion{$i},
          $sealso{$i}, $listing{$i}, $descriptions{$i}, $city{$i},
          $name{$i}, $linkurl{$i}) = split(/","/,$line);
 
          # handle extra "
          $contactid{$i} =~ s/^"//;
          $linkurl{$i}   =~ s/"$//;
 
             print "line: $line\n";
		    print "\$i $i\n";
			$i++;
	    }
}

# It's still much too clumsy. So I asked comp.lang.perl.moderated for a more
# Perlish WTDI:

Date: Fri, 30 Apr 1999 17:52:33 -0700
Subject: Seeking another WTDI
Newsgroups: comp.lang.perl.moderated

Suppose you have a flat file data file, where the fields are interesting,
e.g. an address file:

    Brown, Vicki, PO Box 1269, San Bruno, CA, 94066

and you want to read that file, break each line into fields, and store the
fields in an array

    $i = 0;
    while(<READ>) {
       $last[$i], $first[$i], $address[$i], $city[$i],
       $state[$i], $zip[$i] =
            split(/, /);
    }


Is there a slicker WTDI?  I feel like there should be some cool & nifty
Perlish way, e.g. put all the field names (which become the array names)
into an array of their own and then use map or somesuch to magically split
the record into the right pieces and then bump the counter.

@names = qw(last first address city state zip);
and then do something magical with @names and split...



To: clpm@lists.eyrie.org
Newsgroups: comp.lang.perl.moderated
Subject: Re: Seeking another WTDI

I'd flip it the other way around:

     while (<READ>) {
       chomp;
       my %item;
       @item{qw(last first address city state zip)} = split /, /;
       push @data, \%item;
     }

Then to get to the state of the 475'th user, it's $data[475]{state}.


Date: Sat, 01 May 1999 00:16:06 -0400
Newsgroups: comp.lang.perl.moderated

This code assumes the field names come from the first record, which
happens occasionally.

#!/usr/local/bin/perl -w
use strict;

my %struct;
$_ = <DATA>;
chomp;
my @names = split /, /;
while(<DATA>) {
     chomp;
     my @fields = split /, /;
     my $i = 0;
     foreach (@fields) {
         push @{ $struct{ $names[$i++] } }, $_;
     }
}

That'll create a hash of arrays which I think is what you want.  You
could also create an array of hashes (structs).

while(<DATA>) {
     chomp;
     my %fields;
     @fields{ @names } = split /, /;
     push @structs, \%fields;
}
 
-- --
        |\      _,,,---,,_       Vicki Brown <vlb@cfcl.com>
  ZZZzz /,`.-'`'    -.  ;-;;,_   Journeyman Sourceror: Scripts & Philtres
       |,4-  ) )-,_. ,\ (  `'-'  P.O. Box 1269  San Bruno  CA  94066
      '---''(_/--'  `-'\_) http://www.cfcl.com/~vlb  http://www.macperl.org

==== Want to unsubscribe from this list? (Don't you love us anymore?)
==== Well, if you insist... Send mail with body "unsubscribe" to
==== fwp-request@technofile.org

</x-flowed>