4

最も一般的な emp テーブルを CSV としてエクスポートしました。各列名をハッシュキーとして取得し、値を配列に格納したいと思います。

以下はコードです

 use Data::Dumper;
    open($fh,"<EMP.csv");
    %hash = ();

    local $/= "\n";

    while(<$fh>){

         @columnNames = split(/,/,$_) if $. ==1;     
         @columnValues = split(/,/,$_);  
          push @{hash->{@columnNames}} ,@columnValues;       
    }

    print Dumper(\%hash);

ハッシュを印刷しようとすると、これが得られます

$VAR1 = {
          '8' => [
                   '"EMPNO"',
                   '"ENAME"',
                   '"JOB"',
                   '"MGR"',
                   '"HIREDATE"',
                   '"SAL"',
                   '"COMM"',
                   '"DEPTNO"
',
                   '"7839"',
                   '"KING"',
                   '"PRESIDENT"',
                   '""',
                   '"11/17/1981"',
                   '"5000"',
                   '""',
                   '"10"
',

しかし、私は代わりにこれを期待しています

$VAR1 = { '"EMPNO"'=>[12,3,4,5,6,7,8,9],
          '"EMPNAME"'=>["pavan","kumar"...],

};
4

3 に答える 3

5

push ステートメントでスライスを使用しようとしていますが、うまくいきません。配列はスカラー コンテキストになります。そのため、 key が表示されます8。値を配列にプッシュするには、キーをループする必要があります。しかし、なぜそのようにするのですか?

これにはモジュールを使用できますText::CSV。これは、実際の csv 形式があると仮定すると、かなり単純でおそらくより適切です。

use strict;
use warnings;
use Data::Dumper;
use Text::CSV;

my $csv = Text::CSV->new({
        binary  => 1,
        eol     => $/,
    });
my %data;
open my $fh, "<", "yourfile.csv" or die $!;
$csv->column_names ($csv->getline($fh));          # get header names

while (my $row = $csv->getline_hr($fh)) {         # get hashref with values
    for my $key (keys %$row) {
        push @{$data{$key}}, $row->{$key};        # store values
    }
}
print Dumper \%data;
于 2013-07-03T11:02:30.627 に答える
1

この行を書き直してください

push @{hash->{@columnNames}} ,@columnValues; 

に:

foreach my $columnName (@columnNames) {
    my $columnValue = shift @columnValues;
    push @{ $hash{$columnName} }, $columnValue;
}
于 2013-07-03T10:38:19.147 に答える
1

問題は次のとおりです。

push @{hash->{@columnNames}} ,@columnValues;

@columnNamesハッシュのキーとして使用しようとしています。Perl は自動的にこれをスカラー コンテキストで受け取り、配列に 8 つの値があるため、キーを与えます。8

あなたがしたいことは、CSV の最初の行 (列名を含む) を特別なものとして扱うことです。これは、これらが配列のキーになるためです。

my @column_names = read_csv_row; #Column names
my %employee_hash;
for my $column ( @column_names ) {
    $employee_hash{$column} = [];
}

これにより、配列への参照への列名でキー付けされたハッシュが得られます。CSV テーブルの各行を読み取り、各フィールドを正しい列ハッシュにプッシュする必要があります。

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];
    }
}

これは、CSV 行から各フィールドを取得し、%employee_hash. @column_names各行と同じ順序になっていることを利用しています。したがって、$column_names[$field_number]は正しいハッシュ キーであり、これは$employee_fields[$field_num].

ただし、投稿で述べた構造は、おそらくあなたが本当に望んでいるものではありません. あなたが望むのは次のようなものです:

%VAR = {
           7839 =>   {
                        ENAME    => "KING",
                        JOB      => "PRESIDENT",
                        MGR      => "",
                        HIREDATE => "11/17/1981",
                        SAL      => "5000",
                        COMM     => "",
                        DEPTNO   => "10",
                     }
      }

これにより、従業員番号によって各従業員がキーになり、関連するすべての従業員フィールドがその値の一部になります。次に、従業員番号 7839 の役職は で$employee{7839}->{JOB}あり、その従業員の名前は であると言えます$employee{7839}->{NAME}。このようにして、各従業員に関するすべての情報が 1 つのレコードにまとめられます。

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 = <DATA> 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

ちなみに、このコードはまだテストしていません。(今それを行い、必要な修正を行います)。CSV ファイルを読み取るためのより良い方法を試してみたいと思うかもしれませんしText::CSV、これらの構造を作成するのにも役立つかもしれません (私は長い間使用していないので、その機能のすべてを覚えているわけではありません)。 )。ただし、従業員構造を、従業員番号をキーとする最初のハッシュと、フィールドをキーとするサブハッシュを持つハッシュのハッシュにする方が、配列のハッシュよりもはるかに優れていることがわかると思います。

于 2013-07-03T12:03:43.430 に答える