не могу получить массив хэшей в perl

У меня есть данные CSV сотрудников, и я пытаюсь вставить хэш каждого сотрудника в массив

open($empOutFh,">empOut.txt")
    $hash= [];
    while(<$empFh>) {
        @columnNames = split /,/, $_ if $.==1;
        @columnValues = split /,/, $_;
        %row = map{$_=>shift @columnValues}@columnNames;
        push @$hash,\%row;
    } 
    print Dumper($hash);

Я получаю вывод

$VAR1 = [
          {
            'emp_no' => '11000',
            'hire_date
' => '1988-08-20
',
            'birth_date' => '1960-09-12',
            'gender' => 'M',
            'last_name' => 'Bonifati',
            'first_name' => 'Alain'
          },
          $VAR1->[0],
          $VAR1->[0],
          $VAR1->[0]
      ]

Но когда я пытаюсь напечатать каждую строку, она каждый раз показывает разные хэши строк.


person pavan    schedule 07.07.2013    source источник


Ответы (2)


Проблема в том, что вы используете один хэш %row, поэтому \%row всегда относится к одному и тому же хешу. Каждый раз, когда вы присваиваете %row, вы не устанавливаете для него новый хэш, вы просто очищаете тот же хэш и повторно заполняете его (таким образом косвенно влияя на каждый элемент вашего массива).

Чтобы это исправить, вам нужно создавать новый хеш в каждой итерации цикла. Минимальным изменением в вашем коде будет объявление %row как лексической переменной с локальной областью действия с помощью оператора my:

        my %row = map { $_ => shift @columnValues } @columnNames;
        push @$hash, \%row;

Другой вариант — полностью исключить промежуточную переменную и просто генерировать ссылку на новый анонимный хэш при каждом проходе:

        push @$hash, { map { $_ => shift @columnValues } @columnNames };
person ruakh    schedule 07.07.2013

Если вы не можете заставить map работать должным образом, используйте вместо этого цикл foreach. Уметь поддерживать код важнее, чем быть умным.

#!/usr/bin/env perl

use strict;
use warnings;

# --------------------------------------
use Data::Dumper;

# Make Data::Dumper pretty
$Data::Dumper::Sortkeys = 1;
$Data::Dumper::Indent   = 1;

# Set maximum depth for Data::Dumper, zero means unlimited
local $Data::Dumper::Maxdepth = 0;

# --------------------------------------

# open($empOutFh,">empOut.txt")
my $emp_file = 'empOut.txt';
open my $emp_out_fh, '>', $emp_file or die "could not open $emp_file: $!\n";

#     $hash= [];
my @emps = ();
my @columnNames = ();

#     while(<$empFh>) {
while( my $line = <$empFh> ){
    chomp;

#         @columnNames = split /,/, $_ if $.==1;
    if( $. == 1 ){
        @columnNames = split /,/, $line;
        next;
    }

#         @columnValues = split /,/, $_;
    my @columnValues = split /,/, $line;
    my %row = ();

#         %row = map{$_=>shift @columnValues}@columnNames;
    for my $i ( 0 .. $#columnNames ){
        $row{$columnNames[$i]} = $columnValues[$i];
    }

#         push @$hash,\%row;
    push @emps, \%row;

#     } 
}

#     print Dumper($hash);
print Dumper \@emps;
person shawnhcorey    schedule 07.07.2013