Чтение в CSV-файле на Perl - PullRequest
       0

Чтение в CSV-файле на Perl

4 голосов
/ 20 декабря 2011

Я читал файлы в Perl раньше, но не тогда, когда в CSV-файле есть значения, которые мне нужны в разных строках. Я предполагаю, что мне нужно создать массив, смешанный с хэш-ключами, но я здесь вне своей лиги.

В основном мой CSV-файл имеет следующие столбцы: branch, job, timePeriod, periodType, day1Value, day2Value, day3Value, day4Value, day4Value, day6Value и day7Value.

Значения 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,

1012 * Etc. *

Мне нужно вывести файл, который забирает эти данные и ключи из веток, задания, timePeriod и дня. Мой вывод будет перечислять каждое значение periodType для одного конкретного дня, а не одно значение periodType для всех семи.

Например -

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

В строке выше, последние 3 значения представляют три periodTypes (Overtime, Regular и Variance) day1Values.

Как вы можете видеть, моя проблема в том, что я не знаю, как загрузить данные в память таким образом, который позволяет мне извлекать данные из разных строк и успешно выводить их. Я только раньше разбирал единственные строки.

Ответы [ 2 ]

15 голосов
/ 20 декабря 2011

Если вам не нравится боль, используйте Text::CSV и его родственников Text::CSV_XS и Text::CSV_PP.

Однако, это может быть более легкой частью этой проблемы. После того, как вы прочитали и проверили, что строка заполнена, вам необходимо добавить соответствующую информацию в правильно хешированные ключи. Возможно, вам также придется довольно близко ознакомиться со ссылками.

Возможно, вы создадите хеш %BranchData с ключом ветви. Каждый элемент этого хеша будет ссылкой на хеш, заданный заданием; и каждый элемент в нем будет ссылаться на хеш, заданный timePeriod, и каждый элемент в нем будет ссылаться на массив с ключом по номеру дня (с использованием индексов 1..7; он немного выделяет пространство, но шансы получить это верно намного больше, хотя не связывайтесь с $[!). И каждый элемент массива будет ссылкой на хеш, заданный тремя типами периодов. Ой!

Если все работает хорошо, типовое задание может выглядеть примерно так:

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

Получите удовольствие, забрав его отсюда!

4 голосов
/ 20 декабря 2011

У меня нет непосредственного опыта с этим, но вы можете использовать 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"), поэтому вам придется проверять согласованное форматирование (и применять его) при создании хеша, описанного выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...