perl - 在 Perl 中读取 CSV 文件

标签 perl csv

我以前读过 Perl 中的文件,但当 CSV 文件在不同的行上具有我需要的值时,我没有。我假设我必须创建一个与哈希键混合的数组,但我在这里不合群。

基本上,我的 CSV 文件有以下列:branch, job, timePeriod, periodType, day1Value, day2Value, day3Value, day4Value, day4Value, day6Value , 和 day7Value .

day* 值分别表示一周中每一天的 periodType 值。

例如 -

东,庄家,9AM-12PM,加类,4.25,0,0,1.25,1.5,1.5,0,0
西,电工,12PM-5PM,常规,4.25,0,0,-1.25,-1.5,-1.5,0,0
北,看门人,5PM-12AM,方差,-4.25,0,0,-1.25,-1.5,-1.5,0,0
南,经理,12A-9AM,加类,77.75,14.75,10,10,10,10,10,

等等。

我需要输出一个文件,将这些数据和键从分支、作业、时间段和日期中取出。我的输出将列出一个特定日期的每个 periodType 值,而不是所有七个的一个 periodType 值。

例如 -

南,经理,12A-9AM,77.75,14.75,16

在上面的行中,最后 3 个值代表三个 periodTypes(超时、常规和方差)day1Values .

如您所见,我的问题是我不知道如何以一种允许我从不同行提取数据并成功输出的方式将数据加载到内存中。我以前只解析过单数行。

最佳答案

除非您喜欢疼痛,否则请使用 Text::CSV 及其亲属 Text::CSV_XS Text::CSV_PP .

然而,这可能是这个问题中比较容易的部分。一旦您阅读并验证该行是完整的,您需要将相关信息添加到正确键入的哈希中。您可能还必须非常熟悉引用资料。

您可以创建一个哈希 %BranchData由分支键入。该散列的每个元素都是对作业键入的散列的引用;并且其中的每个元素都是对由 timePeriod 键入的哈希的引用,并且其中的每个元素都将引用由天数键入的数组(使用索引 1..7;它稍微过度分配空间,但获得的机会它的权利要大得多;不过不要乱用$[!)。并且数组的每个元素都是对由三种句点类型键入的散列的引用。哎哟!

如果一切正常,一个原型(prototype)分配可能是这样的:

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

您将迭代元素 1..7 和 'day1' .. '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
                }
            ]
        }
    }
};

从这里开始玩得开心!

关于perl - 在 Perl 中读取 CSV 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8570488/

相关文章:

perl - 是否有用于向 Selenium 发送命令的解释器?

perl - Perl 中的核心、供应商和站点位置有什么区别?

php - 如何将 Perl 脚本的输出包含到 PHP 页面中?

perl - 如何在生产 Web 服务器上的 Apache/mod_perl 下测试 Web Perl 模块?

python - 使用 python 的 csv 文件中的列中的唯一元素

python - “系列”对象是可变的,因此它们不能被散列错误调用 to_csv

perl - 使用 Dancer 和 Postgres 的简单登录/授权系统

sql - 使用格式文件在 SQL 中批量插入 csv 以删除双引号

python - 使用 pandas 缓存 CSV 读取数据以进行多次运行

javascript - 从 Node 中解析的 csv 文件构建对象数组