Search code examples
perldata-dumper

perl printing hash of arrays with out Data::Dumper


Here is the code, I know it is not perfect perl. If you have insight on how I an do better let me know. My main question is how would I print out the arrays without using Data::Dumper?

#!/usr/bin/perl
use Data::Dumper qw(Dumper);

use strict;
use warnings;

open(MYFILE, "<", "move_headers.txt") or die "ERROR: $!";

#First split the list of files and the headers apart
my @files;
my @headers;
my @file_list = <MYFILE>;
foreach my $source_parts (@file_list) {
  chomp($source_parts);
  my @parts = split(/:/, $source_parts);
  unshift(@files, $parts[0]);
  unshift(@headers, $parts[1]);
}

# Next get a list of unique headers
my @unique_files;
foreach my $item (@files) {
  my $found = 0;
  foreach my $i (@unique_files) {
      if ($i eq $item) {
        $found = 1;
        last;
      }
  }
  if (!$found) {
    unshift @unique_files, $item;
  }
}
@unique_files = sort(@unique_files);

# Now collect the headers is a list per file
my %hash_table;
for (my $i = 0; $i < @files; $i++) {
  unshift @{ $hash_table{"$files[$i]"} }, "$headers[$i]";
}

# Process the list with regex
while ((my $key, my $value) = each %hash_table) {
  if (ref($value) eq "ARRAY") {
    print "$value", "\n";
  }
}

Solution

  • You're doing a couple things the hard way. First, a hash will already uniqify its keys, so you don't need the loop that does that. It appears that you're building a hash of files, with the values meant to be the headers found in those files. The input data is "filename:header", one per line. (You could use a hash of hashes, since the headers may need uniquifying, but let's let that go for now.)

    use strict;
    use warnings;
    open my $files_and_headers, "<", "move_headers.txt" or die "Can't open move_headers: $!\n";
    
    my %headers_for_file;
    while (defined(my $line = <$files_and_headers> )) {
            chomp $line;
            my($file, $header) = split /:/, $line, 2;
            push @{ $headers_for_file{$file} }, $header;
    }
    
    # Print the arrays for each file:
    foreach my $file (keys %headers_for_file) {
        print "$file: @{ $headers_for_file{$file}}\n";
    }
    

    We're letting Perl do a chunk of the work here:

    1. If we add keys to a hash, they're always unique.
    2. If we interpolate an array into a print statement, Perl adds spaces between them.
    3. If we push onto an empty hash element, Perl automatically puts an empty anonymous array in the element and then pushes onto that.