2011-12-20 24 views
4

以前はPerlでファイルを読み込んでいましたが、CSVファイルに異なる行に必要な値が入っていませんでした。私はハッシュキーと混在した配列を作成しなければならないと想定していますが、私はここリーグから外れています。PerlでのCSVファイルの読み込み

基本的に私のCSVファイルの列は、branch, job, timePeriod, periodType, day1Value, day2Value, day3Value, day4Value, day4Value, day6Valueday7Valueです。

day *の値は、それぞれの曜日のperiodTypeの値を表します。例については

-

East,Banker,9AM-12PM,Overtime,4.25,0,0,1.25,1.5,1.5,0,0 
West,Electrician,12PM-5PM,Regular,4.25,0,0,-1.25,-1.5,-1.5,0,0 
North,Janitor,5PM-12AM,Variance,-4.25,0,0,-1.25,-1.5,-1.5,0,0 
South,Manager,12A-9AM,Overtime,77.75,14.75,10,10,10,10,10,

私は出力にブランチのオフこのデータとキーを受け取り、ファイル、仕事、時間期間、および日を必要としています。私の出力は、すべての7つのperiodType値ではなく、特定の1日の各periodType値をリストします。例えば

- 上記の行で

South,Manager,12A-9AM,77.75,14.75,16

、最後の3つの値は、三periodTypes(残業、レギュラー、及び分散)day1Valuesを表します。

私の問題は、データをさまざまな行から引き出して正常に出力できるような方法でデータをメモリに読み込む方法がわからないことです。私は前に特異な行だけを解析しました。

答えて

14

痛みが好きでない限り、Text::CSVとその親戚Text::CSV_XSText::CSV_PPを使用してください。

ただし、これはこの問題の一部です。行が完了したことを確認して検証したら、適切な鍵を付けられたハッシュに関連情報を追加する必要があります。あなたはおそらく、あまりにも親密に参照に精通しなければならないでしょう。

ブランチによってキーが設定された%BranchDataハッシュを作成することがあります。そのハッシュの各要素は、ジョブによってキー付けされたハッシュへの参照になります。その中の各要素はtimePeriodでキーされたハッシュへの参照となり、その要素の各要素は日番号で配列された配列への参照となります(インデックス1..7を使用して、スペースを少し割り振りますが、それは大いに大きいです;しかし、$[と混乱しないでください!)。配列の各要素は、3つのピリオドの種類によってキーが設定されたハッシュへの参照になります。おお!

すべてがうまく機能している場合は、プロトタイプの割り当てのようなものかもしれません:あなたは要素の反復処理されるだろう

$BranchData{$row{branch}}->{$row{job}}->{$row{period}}->[1]->{$row{p_type}} += 
    $row{day1}; 

1..7と「1日目」..「day7」;そこで行うデザイン作業にはちょっとしたクリーンアップがあります。

あなたは物事を正しく初期化することを心配する必要があります(あるいは、そうでないかもしれません - Perlはあなたのためにそれを行います)。私は行がブランチ、ジョブ、期間、期間タイプ(p_type)、そして毎日( 'day1'、.. 'day7')のキーを持つ直接ハッシュ(ハッシュ参照ではなく)として返されると仮定しています。 。

事前に必要な日が分かっている場合は、すべての日数が累積されるのを避けることができますが、より一般化されたレポート作成をすべてのデータを常に読み込んで蓄積することが簡単になり、データ全体を処理する必要があります。


それは私が一緒にこのコードをハッキングしてきた問題は十分魅力的でした。私はそれが最適であるかどうかは疑問だが、うまくいく。あなたのサンプルデータが与えられ

#!/usr/bin/env perl 
# 
# SO 8570488 

use strict; 
use warnings; 
use Text::CSV; 
use Data::Dumper; 
use constant debug => 0; 

my $file = "input.csv"; 
my $csv = Text::CSV->new({ binary => 1, eol => $/ }) 
        or die "Cannot use CSV: ".Text::CSV->error_diag(); 
my @headings = qw(branch job period p_type day1 day2 day3 day4 day5 day6 day7); 
my @days  = qw(day0 day1 day2 day3 day4 day5 day6 day7); 
my %BranchData; 

open my $in, '<', $file or die "Unable to open $file for reading ($!)"; 

$csv->column_names(@headings); 
while (my $row = $csv->getline_hr($in)) 
{ 
    print Dumper($row) if debug; 
    my %r = %$row; # Not for efficiency; for notational compactness 
    $BranchData{$r{branch}} = { } if !defined $BranchData{$r{branch}}; 
    my $branch = $BranchData{$r{branch}}; 
    $branch->{$r{job}} = { } if !defined $branch->{$r{job}}; 
    my $job = $branch->{$r{job}}; 
    $job->{$r{period}} = [ ] if !defined $job->{$r{period}}; 
    my $period = $job->{$r{period}}; 
    for my $day (1..7) 
    { 
     # Assume that Overtime, Regular and Variance are the only types 
     # Otherwise, you need yet another level of checking whether elements exist... 
     $period->[$day] = { Overtime => 0, Regular => 0, Variance => 0} if !defined $period->[$day]; 
     $period->[$day]->{$r{p_type}} += $r{$days[$day]}; 
    } 
} 

print Dumper(\%BranchData); 

、この出力は次のようになります。

$VAR1 = { 
    'West' => { 
     'Electrician' => { 
      '12PM-5PM' => [ 
       undef, 
       { 
        'Regular' => '4.25', 
        'Overtime' => 0, 
        'Variance' => 0 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => 0, 
        'Variance' => 0 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => 0, 
        'Variance' => 0 
       }, 
       { 
        'Regular' => '-1.25', 
        'Overtime' => 0, 
        'Variance' => 0 
       }, 
       { 
        'Regular' => '-1.5', 
        'Overtime' => 0, 
        'Variance' => 0 
       }, 
       { 
        'Regular' => '-1.5', 
        'Overtime' => 0, 
        'Variance' => 0 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => 0, 
        'Variance' => 0 
       } 
      ] 
     } 
    }, 
    'South' => { 
     'Manager' => { 
      '12A-9AM' => [ 
       undef, 
       { 
        'Regular' => 0, 
        'Overtime' => '77.75', 
        'Variance' => 0 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => '14.75', 
        'Variance' => 0 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => 10, 
        'Variance' => 0 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => 10, 
        'Variance' => 0 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => 10, 
        'Variance' => 0 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => 10, 
        'Variance' => 0 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => 10, 
        'Variance' => 0 
       } 
      ] 
     } 
    }, 
    'North' => { 
     'Janitor' => { 
      '5PM-12AM' => [ 
       undef, 
       { 
        'Regular' => 0, 
        'Overtime' => 0, 
        'Variance' => '-4.25' 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => 0, 
        'Variance' => 0 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => 0, 
        'Variance' => 0 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => 0, 
        'Variance' => '-1.25' 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => 0, 
        'Variance' => '-1.5' 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => 0, 
        'Variance' => '-1.5' 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => 0, 
        'Variance' => 0 
       } 
      ] 
     } 
    }, 
    'East' => { 
     'Banker' => { 
      '9AM-12PM' => [ 
       undef, 
       { 
        'Regular' => 0, 
        'Overtime' => '4.25', 
        'Variance' => 0 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => 0, 
        'Variance' => 0 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => 0, 
        'Variance' => 0 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => '1.25', 
        'Variance' => 0 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => '1.5', 
        'Variance' => 0 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => '1.5', 
        'Variance' => 0 
       }, 
       { 
        'Regular' => 0, 
        'Overtime' => 0, 
        'Variance' => 0 
       } 
      ] 
     } 
    } 
}; 

はここからそれを取って楽しんでください!

+0

私がUTF-8を扱うために使用する 'Text :: CSV :: Encoded'も考慮する必要があります。 – reinierpost

+0

私はこのコードが私の必要とするものだと信じています!
South、Manager、12A-9AM、77.75,14.75,16
上記の行の最後の3つの値は、3つのperiodTypes(Overtime、Regular、およびVariance)を表しています。 )day1の値。 – user1107055

4

私は直接経験はありませんが、DBD::CSVを使用して、必要な集計を計算するために必要な比較的単純なSQLクエリを渡すことができます。

あなたがが、それを苦労してやっと主張した場合、あなたができるループを通るとハッシュリファレンスの以下のハッシュでデータを収集します。

(
    "branch1,job1,timeperiod1"=> 
    { 
     "overtime"=>"overtimeday1value1", 
     "regular"=>"regulartimeday1value1", 
     "variance"=>"variancetimeday1value1" 
    }, 
    "branch2,job2,timeperiod2"=> 
    { 
     "overtime"=>"overtimeday1value2", 
     "regular"=>"regulartimeday1value2", 
     "variance"=>"variancetimeday1value2" 
    }, 
    #etc 
); 

し、それに応じてキーによるそしてちょうどループ。ただし、この方法ではキーの一貫した書式設定に依存します(例:"East,Banker,9AM-12PM""East, Banker, 9AM-12PM"と同じではありません)。したがって、上記のハッシュを作成しながら一貫性のある書式設定(および適用)を確認する必要があります。

+0

右 - 私は値を変えることができるようにしたいと思っていたし、AKAハードコードではないプログラムを壊さないだろう。 – user1107055

+0

@ user1107055 - 私はあなたが私を誤解していると思います。あなたがそれを難し​​い方法でやりたいのであれば、ファイルを一行ずつ読み、上のハッシュリファレンスのハッシュを作成する必要があります。したがって、スクリプトでこれを行い、ファイルを変更してスクリプトを再実行すると、別のハッシュ(および異なる出力)が得られます。 –

+1

私は 'DBD :: CSV'を使用しています(実際はCSVファイルで任意のSQLクエリを実行できる単純なラッパースクリプト' csvsql'を使用しています)。 – reinierpost

関連する問題