2010-06-01 11 views
2

Je fais un petit projet de datamining où un script perl récupère des informations d'une base de données SQL et les analyse. Les données sont composées de plusieurs horodatages. Je veux trouver combien d'un type particulier d'horodateur existe un jour particulier. Malheureusement, c'est mon premier script perl, et la nature de perl quand il s'agit de hachages et de tableaux me déroute pas mal.Nouvel utilisateur Perl: utilisation d'un hachage de tableaux

segment de code:

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

Je continue de recevoir des erreurs de syntaxe dans la boucle pour les valeurs incrémenter. Aussi, étant donné que j'utilise strict et les avertissements, Perl va-t-il automatiquement créer des tableaux de bonnes valeurs quand j'y accède à l'intérieur du hachage, ou est-ce que j'obtiendrai des erreurs hors-limites partout?

Merci pour toute aide, Zach

+3

Est-ce que ce code compile? 'for (...) STATEMENT' est normalement une erreur dans Perl. Les accolades sont obligatoires - il faut que ce soit 'for (...) {STATEMENT}' – mob

Répondre

5

Erreurs:

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

Perl ne supporte pas les boucles nues/blocs conditionnels. Ou plutôt, it does, mais pas comme ça. Cela peut fonctionner en PHP, mais pas en Perl. Vous voulez enfermer ces derniers dans des blocs:

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

Depuis hash en Perl ne peut adapter les types de données scalaires en eux, afin de stocker un tableau entier à l'intérieur d'un hachage, nous sommes va devoir le faire par référence. Voici un rapide tutoriel sur les références du tableau:

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" 

Qu'est-ce que votre code fait ci-dessus est de tirer la valeur à la clé de hachage $proposal[$i] de hachage %values, puis utilisez (un scalaire) comme un tableau (il est pas un tableau).

Comme je l'ai dit avant, vous pouvez l'utiliser comme un tableau référence mais pas un tableau:

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

Suggestions:

  • écriture my $foo; for ($foo = 0; $foo <= 5; $foo++) est écrit plus facilement " for my $foo (0 .. 5) "ou" foreach my $foo (0 .. 5) ". C'est, en substance, comment la plupart des gens le font. Il est à noter que for et foreach sont interchangeables – c'est une question de préférence et de lisibilité. Veuillez, pour des raisons de lisibilité, indenter votre code avec plus d'un espace. Une bonne règle est quatre espaces, ou une tabulation. St. Larry Wall pensait aux langues que les gens parlent et écrivent lorsqu'il a conçu Perl.

  • Je vous recommande de rechercher le bon moyen (correct, ici, ce qui signifie le plus efficace) d'écrire des boucles for. Il y a quelques habitudes qui peuvent aboutir à des programmes plus rapides dans l'ensemble si elles ont beaucoup de longues boucles for.Par exemple:

    • ++$foo est plus efficace que $foo++. Cela découle de la structure interne:
      • $foo++ incrémente la variable, soustrait 1, puis renvoie le résultat, alors que
      • ++$foo incrémente la variable et le renvoie. Moins d'opérations = plus rapide.
    • Une comparaison inférieure à ou égale est moins efficace qu'une simple comparaison inférieure à. Encore une fois, cela est dû au nombre d'opérations que votre ordinateur doit effectuer. for ($x=0; $x<=5; ++$x) est mieux écrit comme for ($x=0; $x<6; ++$x).
  • Perl possède de merveilleux contrôles en boucle. Certains, comme map, sont très puissants.

+1

$ values ​​{$ proposition [$ i]} [$ i] est parfaitement bien. Vous n'avez besoin que de la flèche -> pour déréférencer un scalaire au début. Exemple: my $ arr_ref = [{a => 'f', b => 'g'}, {c => 'h', d => 'i'}]; print $ arr_ref -> [0] {b}; – DougWebb

+0

@DougWebb - Vous avez parfaitement raison; Perl compense l'absence de '->' dans l'expression, même dans 'use strict'. Je vais le laisser tel quel pour donner au PO une idée de ce qui se passe en ce qui concerne les structures de données. – amphetamachine

+1

J'ai une très bonne idée de la façon dont les structures fonctionnent maintenant. Mon code fonctionne et a l'air un peu plus propre! Je suis toujours en train de déterminer quand Perl fait et ne fait pas les choses automatiquement, mais c'est une bonne poussée dans la bonne direction. Merci a tous! –