Limbic~Region has asked for the wisdom of the Perl Monks concerning the following question:

All:
I have a bunch of files whose names relate to the data they contain.
For instance:

val1.a
val1.b
val1.c

val2.a
val2.b
val2.c

val3.a
val3.b
val3.c
The first part (val#) could be any unique string, but the second part (a,b,c) will always be one of those three strings.

Each file will contain a tab delimited line that I suck into an array such as:

entry1 entry2 entry3 entry4 entry5
entry1 entry2 entry3 entry4 entry5
entry1 entry2 entry3 entry4 entry5

After reading in all the files, what I need to know to do is:

  • Get a list of unique first values to loop over
  • For each value in the list loop over the second file name part (a,b,c)
  • For each second file name part, loop over each line in the file

    It seems to me that a HoHoA is in order, but I can't seem to make it work. If each file only had one line it wouldn't be that hard - I would just say = to, but the next entry in the file overwrites it.

    Any and all help will be appreciated.

    L~R

  • Replies are listed 'Best First'.
    Re: How should I store/retrieve my data
    by BrowserUk (Patriarch) on Jan 23, 2003 at 18:49 UTC

      Untested.

      my %files for my $file (@files) { my ($name,$sfx) = split'.', $file; open FILE, '<', $file or doe $!; push @{ $file{$name}{$sfx} }, <FILE>; close FILE; } for my $uniq ( keys %files ) { for my $sfx ( 'a' .. 'c' ) { for my $line ( @{ $files{$uniq}{$sfx} } ) { #do something with line } } }

      Examine what is said, not who speaks.

      The 7th Rule of perl club is -- pearl clubs are easily damaged. Use a diamond club instead.

        Thanks BrowserUk!
        This was sufficient to get over my hurdle, though I had to add/modify a few things.

        L~R

    Re: How should I store/retrieve my data
    by tall_man (Parson) on Jan 23, 2003 at 18:06 UTC
      Here's a trick that will save a level in your HoHoA. Use slurp mode to read the whole contents of each file into a string, and save the whole string in the HoH. When you get to the point of needing to interate over the lines, split the string on newlines.
      sub readFile { my $filename = shift; my $fh = new FileHandle("<" . $filename); local $/ = undef; # slurp mode my $data = <$fh>; $fh->close; return $data; }
    Re: How should I store/retrieve my data
    by jdporter (Paladin) on Jan 23, 2003 at 21:20 UTC
      my %h; for my $file ( glob "*.[abc]" ) { my( $file_k0, $file_k1 ) = $file =~ /(.*)\.(.*)/; local @ARGV = ($file); while (<>) { chomp; push @{ $h{$file_k0}{$file_k1} }, [ split /\t/ ]; } }
      Then what you have in %h is a hash of hash of array of array. The two levels of hash are for the two parts of the filename. The values of the second-level hash are arrays representing the lines of the file. Each line is an array of the tab-delimited fields.

      So, to iterate over the thing fully, you could do:
      for my $file_k0 ( sort keys %h ) { for my $file_k1 ( sort keys %{ $h{$file_k0} } ) { print "File $file_k0.$file_k1 -\n"; for my $line_ar ( @{ $h{$file_k0}{$file_k1} } ) { for my $field ( @$line_ar ) { print "\t$field"; } print "\n"; } } }

      jdporter
      The 6th Rule of Perl Club is -- There is no Rule #6.