Новый пользователь Perl: использование хэша массивов - PullRequest
2 голосов
/ 01 июня 2010

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

Сегмент кода:

my %values=();#A hash of the total values of each type of data of each day.
#The key is the day, and each key stores an array of each of the values I need.
my @proposal;
#[drafted timestamp(0), submitted timestamp(1), attny approved timestamp(2),Organiziation approved timestamp(3), Other approval timestamp(4), Approved Timestamp(5)]
while(@proposal=$sqlresults->fetchrow_array()){
 #TODO: check to make sure proposal is valid
 #Increment the number of timestamps of each type on each particular date
 my $i;
for($i=0;$i<=5;$i++)
$values{$proposal[$i]}[$i]++;
#Update rolling average of daily 
#TODO: To check total load, increment total load on all dates between attourney approve date and accepted date
for($i=$proposal[1];$i<=$proposal[2];$i++)
 $values{$i}[6]++; 
}

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

Спасибо за любую помощь, Zach

1 Ответ

5 голосов
/ 01 июня 2010

Ошибка:

for($i=0;$i<=5;$i++)
    $values{$proposal[$i]}[$i]++;
for($i=$proposal[1];$i<=$proposal[2];$i++)
    $values{$i}[6]++; 

Perl не поддерживает голые циклы / условные блоки. Или, скорее, это делает , но не так. Это может работать в PHP, но не в Perl. Вы захотите заключить их в блоки:

for($i=0;$i<=5;$i++) {
    $values{$proposal[$i]}[$i]++;
}
for($i=$proposal[1];$i<=$proposal[2];$i++) {
    $values{$i}[6]++;
}

$values{$proposal[$i]}[$i]++;

Поскольку хеши в Perl могут вмещать в них только скалярные типы данных, для хранения всего массива внутри хеша нам придется делать это по ссылке. Вот краткое руководство по ссылкам на массивы:

my $arr_ref = [];               # empty array reference
my $arr_ref = [ 1, 2, 'foo', ]; # initialize with values
my $arr_ref = \@arr;            # reference an existing array;
                                # does not make copy, but provides a
                                # read-write handle to the array

$arr_ref->[0];                  # index the first (index 0) element of the array
@{$arr_ref}[ 0 .. 4 ];          # index elements number one through five (0-4) of the array
                                # through what's called an "array slice"

То, что делает ваш код выше, это извлечь значение из хеш-ключа $proposal[$i] из хеша %values, затем использовать его (скаляр) как массив (это не массив).

Как я уже говорил, вы можете использовать его как массив , ссылку , но не как массив:

                    # v-- note the arrow
$values{$proposal[$i]}->[$i]++;

Предложения:

  • Запись my $foo; for ($foo = 0; $foo <= 5; $foo++) легче написать как "for my $foo (0 .. 5)" или "foreach my $foo (0 .. 5)". По сути, именно так и поступает большинство людей. Следует отметить, что for и foreach являются взаимозаменяемыми - это вопрос предпочтений и разборчивости.

  • Пожалуйста, для разборчивости вставьте в код более одного пробела. Хорошее практическое правило - четыре пробела или табуляция. Сент-Ларри Уолл думал о языках, на которых люди говорят и пишут, когда разрабатывал Perl.

  • Я бы порекомендовал исследовать правильный (правильный, здесь, наиболее эффективный) способ написания циклов for. Есть несколько привычек, которые могут привести к более быстрым программам в целом, если в них много длинных циклов for. Например:

    • ++$foo более эффективно, чем $foo++. Это вытекает из внутренних органов:
      • $foo++ увеличивает переменную, вычитает из нее 1, затем возвращает результат, тогда как
      • ++$foo увеличивает переменную и возвращает ее. Меньше операций = быстрее.
    • Сравнение меньше или равно менее эффективно, чем простое сравнение меньше. Опять же, это связано с количеством операций, которые ваш компьютер должен выполнить. for ($x=0; $x<=5; ++$x) лучше написано как for ($x=0; $x<6; ++$x).
  • В Perl есть несколько замечательных элементов управления циклом. Некоторые, такие как map, очень мощные.

...