Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Here's your problem:</p> <pre><code>push @{hash-&gt;{@columnNames}} ,@columnValues; </code></pre> <p>You're trying to use <code>@columnNames</code> as a key in your hash. Perl automatically takes this in a scalar context, thus, giving you a <em>key</em> of <code>8</code> since there are eight values in the array.</p> <p>What you want to do is treat the first row in your CSV (which contains the column names) as special since these will be keys to your array.</p> <pre><code>my @column_names = read_csv_row; #Column names my %employee_hash; for my $column ( @column_names ) { $employee_hash{$column} = []; } </code></pre> <p>This will give you a hash, keyed by column name to references to arrays. You now have to read in each line of your CSV table, and push each field into its correct column hash;</p> <pre><code>while ( my @employee_fields = read_csv_row ) { #Your employee record is in @employee for my $field_num ( 0..$#employee_fields) { push @{ $employee_hash{$column_names[$field_num] }, $employee_fields[$field_num]; } } </code></pre> <p>What this is doing is taking each field from the CSV row and pushing it into its correct array reference in the <code>%employee_hash</code>. I'm taking advantage that <code>@column_names</code> is in the same order as each row. Thus, <code>$column_names[$field_number]</code> is the correct hash key, and that should correspond to the <code>$employee_fields[$field_num]</code>.</p> <p>However, the structure you said in your post is probably not what you really want. What you want is something like this:</p> <pre><code>%VAR = { 7839 =&gt; { ENAME =&gt; "KING", JOB =&gt; "PRESIDENT", MGR =&gt; "", HIREDATE =&gt; "11/17/1981", SAL =&gt; "5000", COMM =&gt; "", DEPTNO =&gt; "10", } } </code></pre> <p>This wil key each employee by their employee number, and all of the related employee fields will be part of that value. Then you can talk about Employee number 7839's job title as being <code>$employee{7839}-&gt;{JOB}</code> and that employee's name being <code>$employee{7839}-&gt;{NAME}</code>. This way, all of the information about each employee is together in a single record:</p> <pre><code>use warnings; use strict; use Data::Dumper; use feature qw(say); my @column_names = read_csv_row(); #Column name my %employee_hash; while ( my @minion_fields = read_csv_row() ) { #Your employee record is in @employee my %minion_hash; my $minion_number = $minion_fields[0]; for my $field_num ( 1..$#minion_fields) { $minion_hash{ $column_names[$field_num] } = $minion_fields[$field_num]; } $employee_hash{$minion_number} = \%minion_hash; } sub read_csv_row { my $row = &lt;DATA&gt; or return; chomp $row; return split /,\s+/, $row; } say Dumper \%employee_hash; __DATA__ empno, name, job, mgr, hiredate, sal, comm, deptno 7839, king, president, , 11/17/1981, 5000, , 10 1234, prince, vice-president, , 10/1/1980, 3000, , 10 </code></pre> <p><strike>By the way, I haven't tested this code yet. (I'll do that now, and make needed corrections).</strike> You may want to play around with <code>Text::CSV</code> which will be a better way of reading in CSV files, and may even help you create these structures (I haven't used it in a long, long time, so I don't remember everything it does). However, I believe that you'll find making your employee structure a hash of hashes with the initial hash keyed by employee number, and the sub-hashes keyed by fields a lot better than a hash of arrays.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload