ianand0204 has asked for the wisdom of the Perl Monks concerning the following question:

I am very new to perl and programming in general. I have been trying to figure out how to convert an array into a hash. The goal is to get an array of files within a directory and then store those in a hash for HTML::Template to display (via the TMPL_LOOP)
use File::Find::Rule; use Data::Dumper; my $rule = File::Find::Rule->new; $rule->file; $rule->name( '*.zone' ); my @files = $rule->in("/home/dns");
This seems to take care of creating my array. The problem lies when converting my array into a hash. The code I have below is what I have come up with, but since the only real data I care about in the hash is the "key" do I need to add a value to it?
%hash = map { $files[$_], $_ + 1 } 0 .. $#files; foreach my $name (sort keys %hash) { my $host = $hash{$name}; print $host; my %row = { name => $name, };
perl test.cgi
141629131217242221182019162310411315587
is the output. What appears to be happening is the foreach loop is iterating over the wrong field, but I can't figure out why.

Replies are listed 'Best First'.
Re: Populating an Array of hash's
by ikegami (Patriarch) on Oct 01, 2008 at 02:26 UTC

    The file names are the keys in your code, but you're printing the values.

    But HTML::Template doesn't want a hash, it wants an array of records, where each record is a hash. In this case, the record only has one field, the file name.

    <TMPL_LOOP NAME=FILES> Name: <TMPL_VAR NAME=NAME><br> </TMPL_LOOP>
    $template->param( FILES => [ map +{ NAME => $_ }, @files ], );

    If you also want a number, just add a field to the hash.

    <TMPL_LOOP NAME=FILES> <TMPL_VAR NAME=NUM>. <TMPL_VAR NAME=NAME><br> </TMPL_LOOP>
    $template->param( FILES => [ map +{ NUM => $_+1, NAME => $files[$_], }, 0..$#files ], );
      But HTML::Template doesn't want a hash, it wants an array of records, where each record is a hash.
      Just a note: If you use HTML::Template::Compiled you don't need that. It can iterate over an array of plain values, or even arrays of arrays. In this case:
      <%loop files %> <%= _ %> <%/loop files %>
      Thanks, that actually did the trick, but I have a question. What does the line below do? It looks like its taking the @files array and mapping them into a hash, which is getting mapped to the array FILES which HTML::Template then parses??
      $template->param( FILES => [ map +{ NAME => $_ }, @files ], );
      What is this line doing?
      map +{ NAME -> $_}

        map +{ NAME => $_ }, LIST
        is another way of writing
        map { { NAME => $_ } } LIST

        The expression { NAME => $_ }

        1. creates a hash,
        2. assigns NAME => $_ to it (creating a key named NAME whose associated value is $_), and
        3. returns a reference to the hash.

        The expression map { { NAME => $_ } } @files

        1. For every element of @files,
          1. sets $_ to the element
          2. executes the sub-expression.
        2. A list is formed from the result of the sub-expressions and returned.

        In other words,

        $template->param( FILES => [ map +{ NAME => $_ }, @files ], );

        could have been written

        my @files_param; for (@files) { push @files_param, { NAME => $_ }; } $template->param(\@files_param);
Re: Populating an Array of hash's
by chrism01 (Friar) on Oct 01, 2008 at 06:34 UTC
    Idiomatic array into a hash

    @hash{@array} = (1) x @array;