difficulter pour coder....

difficulter pour coder.... - Perl - Programmation

Marsh Posté le 19-03-2007 à 12:12:17    

bonjour,
 
je dois coder un petit bout de perl, et comme je suis débutant avec ce langage je ne sais pas trop comment coder mon "algo".
 
voici le problème :
 
j'ai un fichier
 
bscid,siteid,btsid,time,mcc,mnc,lac,ci,c11101,c11102,c11103,c11104,c11105,c11106,c11107,c11108,c11109,c11110,c11111,c11112,c11113,c11114,c11115,c11116
3,1,1,200703090905,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703090910,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703090915,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

3,1,1,200703090920,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703090925,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703090930,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

3,1,1,200703090935,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703090940,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703090945,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

3,1,1,200703090950,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703090955,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703091000,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

 
 
la première ligne c'est le "header" de description...
je dois faire la somme des compteurs (des c... i.e des c11101, c11102, etc...) suivant 4 1/4 d'heures.
 
1 -
 
3,1,1,200703090905,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703090910,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703090915,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

 
 
2-
 
3,1,1,200703090920,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703090925,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703090930,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

 
3-
 
3,1,1,200703090935,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703090940,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703090945,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

 
4-
 
3,1,1,200703090950,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703090955,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703091000,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

 
 
 
la clef de hash pour faire cette somme c'est bscid,siteid,btsid,time finit par 05,10 ou 15,mcc,mnc,lac,ci dans le premier cas
bscid,siteid,btsid,time finit par 20,25 ou 30,mcc,mnc,lac,ci dans le second
bscid,siteid,btsid,time finit par 35,40 ou 45,mcc,mnc,lac,ci dans le troisième
bscid,siteid,btsid,time finit par 50,55 ou 00,mcc,time mnc,lac,ci dans le 4ième
 
les champs bscid,siteid,btsid,mcc,time mnc,lac,ci sont variables, ils sont différents dans tous le fichier à traiter.
 
le résultat est mis dans un tableau agrégé :
 
3,1,1,200703090900,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703090915,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703090930,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703090945,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 
 
quelqu'un peu t'il m'aider à coder cela ??
 
par avance merci a ceux qui prendront le temps de m'aider :bounce:  
 
 

Reply

Marsh Posté le 19-03-2007 à 12:12:17   

Reply

Marsh Posté le 19-03-2007 à 12:17:52    

steve419 a écrit :

je dois coder un petit bout de perl, et comme je suis débutant avec ce langage je ne sais pas trop comment coder mon "algo".


Bon c'est vraiment pas bien compliqué, alors biensur on pourrait te l'écrire en trois lignes zou on en parlerait plus, mais cela perdrait de son coté pédagogique ( AMHA)
.
Prenons les choses dans l'ordre, tu dis que ton algo est fini, tu peux nous le montrer?
Ensuite dis-nous étape par étape ce que tu n'arrives pas à implémenter en perl.
 

Reply

Marsh Posté le 19-03-2007 à 12:25:51    

il faut commencer par lire ton fichier ligne par ligne, puis récupérer les données contenues dans chaque ligne, en tenant compte du fait que les champs sont séparés par des virgules. Ensuite, tu peux commencer à traiter réellement tes données.
 

Code :
  1. while (<> )
  2. {
  3.   my @values = split ',';
  4.   my $min = $value[3] % 100;
  5.   if ($min - 1 < 15)
  6.   {
  7.     # premier 1/4 d'heure
  8.   }
  9.   elsif ($min - 1 < 30)
  10.   {
  11.     #  2eme 1/4 d'heure
  12.   }
  13.   elsif ($min - 1 < 45)
  14.   {
  15.     # 3eme 1/4 d'heure
  16.   }
  17.   else
  18.   {
  19.     # 4eme 1/4 d'heure
  20.   }
  21. }


 
C'est écrit à l'arrache et non testé, mais ça te donne grosso modo une idée du squelette de ton truc.
 
 
 
EDIT: OOPS, désolé anapajari, j'ai détruit une partie de ton travail pédagogique :sweat:

Message cité 1 fois
Message édité par franceso le 19-03-2007 à 12:27:50

---------------
TriScale innov
Reply

Marsh Posté le 19-03-2007 à 14:42:11    

déjà, merci pour votre aide  :jap:  
 
@franceso : les lignes sont mélangées,  
 
200703091000 pour cette valeure tu rentres dans la 1ère condition alors que pour moi c'est le dernier 1/4 d'heure
 
@anapajari : voici ce que je veux coder :
 
1 - pour toutes les lignes du fichier stoquer chaque élément séparé par une virgule dans une table de hash. le nombre de compteur c... peut-être variable, la partie fixe c'est les champs principaux du header à savoir : le couple (bscid-siteid-btsid-mcc-mnc-lac-ci,time) qui constituent ma clef de hash. (en retregnant le champ 'time' au deux dernier chiffre pour apprès faire la somme)
 
voila ce que je veux avoir dans mon table de hachage :
 
hashtab[bscid-siteid-btsid-mcc-mnc-lac-ci,time]=[c1,c2,...cn]
 
ex : hashtab[3-1-1-603-1-3102-16102,05]=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ]
 hashtab[3-1-1-603-1-3102-16102,10]=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ]
 
2- faire la somme :
 
res[i,00][j]=somme des hashtab[i,05][j]+hashtab[i,10][j]+hashtab[i,15][j] pour tous les i (bscid-siteid-btsid-mcc-mnc-lac-ci) de mon tableau pour le 1er 1/4 d'heure et tous les j (c1,c2,...cn)
 
res[i,15][j]=hashtab[i,20][j]+hashtab[i,25][j]+hashtab[i,30][j] pour le 2nd 1/4 d'heure
 
res[i,30][j]=somme des hashtab[i,35][j]+hashtab[i,40][j]+hashtab[i,45][j] pour le 3ième 1/4 d'heure
 
res[i,45][j]=somme des hashtab[i,50][j]+hashtab[i,55][j]+hashtab[i,60][j] pour le 4ième 1/4 d'heure
 
4- reconstituer le fichier résultat en lisant la table res
 
3,1,1,200703090900,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703090915,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703090930,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,1,1,200703090945,603,1,3102,16102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0  
 
 
 
 
le début de mon code :
 
                        my $memoryfile = shift;                   # Array Reference to each open input file  
                        my($line,$time,$key_hash,@dat,@fields);
                        %table_hash;
                        foreach $line (@memoryfile)
                        {
                                chomp($line);
                                if ($line !~ /^bscid/) # la ligne n'est pas la ligne de header
                                {
                                        # line : bscid,siteid,btsid,time,mcc,mnc,lac,ci,c1,c2,..,c(n)
                                        @fields = split(",",$line);
                                        $time = $fields[4];
                                        $time =~ s/^(\d{10})(\d{2})$/$1/;
                                        $heure = $2;
                                        $key_hash = "$fields[0]-$fields-[1]-$fields[2]-$fields[3]-$fields-[5]-$fields-[6]$fields[7]-$fields[8]";
 
 
 
                                        je ne sais pas comment faire a partir d'ici :
                                        $table_hash{$key_hash,$heure} = <c1,c2,..,c(n)>
 
                                }
                        }
 
                        # Update the Input file with the pre-parsed data
                        foreach $cle (keys (%table_hash))
                        {
 
 
                                push @dat, $line;
                        }
 
                        push @dat, $line;
 
                        @{$memoryfile} = @dat;
 
                        return 0;
 
 
 
 
merci pour votre aide  :jap:

Message cité 1 fois
Message édité par steve419 le 19-03-2007 à 14:43:43
Reply

Marsh Posté le 19-03-2007 à 15:30:11    

A mon avis, tu devrais faire une hash de hash ( enfin de référence sur hash), et du coup sur ta ligne en rouge tu aurais quelque chose du style:

Code :
  1. $table_hash{$key_hash}{$heure}{'c1'} += laValeurDeC1;
  2. $table_hash{$key_hash}{$heure}{'c2'} += laValeurDeC2;
  3. ...
  4. $table_hash{$key_hash}{$heure}{'cn'} += laValeurDeCN;


 
A noter que si tes fichiers sont vraiment gros, c'est pas une super bonne idée de se les trimballer dans des tableaux en mémoire...
 

franceso a écrit :

EDIT: OOPS, désolé anapajari, j'ai détruit une partie de ton travail pédagogique :sweat:


pas grave :o
 

Reply

Marsh Posté le 19-03-2007 à 15:46:28    

steve419 a écrit :

200703091000 pour cette valeure tu rentres dans la 1ère condition alors que pour moi c'est le dernier 1/4 d'heure


Au temps pour moi : j'ai mis le -1 au mauvais endroit... Je voulais écrire :

Code :
  1. my $min = ($value[3]-1) % 100;
  2. if ($min < 15)


Ceci dit, ta solution à base de /(\d{10})(\d{2})/ est très bien aussi...
 
 
+1 pour la hash de hash proposée par anapajari.
 


---------------
TriScale innov
Reply

Marsh Posté le 19-03-2007 à 15:48:08    

a noter qu'en me relisant je constate que j'ai bien insisté sur le fait que c'était une hash de référence de hash mais que dans mon code j'ai merdé :o
Il manque un $ ou une flèche, au choix.

Reply

Marsh Posté le 19-03-2007 à 16:48:21    

merci pour votre aide,
 
si je rajoute le predicat suivant : si heure = 05 , 10 ou 15 alors heure = 0  
si heure = 20 , 25 ou 30 alors heure = 15
ou si heure = 35 , 40 ou 45 alors heure = 30
ou  si heure = 50 , 55 ou 00 alors heure = 45
 
je peux directement faire la somme comme je veux avec le code ci dessous de anapajari ( res[i,00][j]=somme des hashtab[i,05][j]+hashtab[i,10][j]+hashtab[i,15][j] pour tous les i (bscid-siteid-btsid-mcc-mnc-lac-ci) de mon tableau pour le 1er 1/4 d'heure et tous les j (c1,c2,...cn) )  
 

Code :
  1. $table_hash{$key_hash}{$heure}{'c1'} += laValeurDeC1;
  2. $table_hash{$key_hash}{$heure}{'c2'} += laValeurDeC2;
  3. ...
  4. $table_hash{$key_hash}{$heure}{'cn'} += laValeurDeCN;


 
est-ce que tu peux m'aider dans le code perl avec ces deux boucles (for par exemple) pour que le nombre de compteur (c...) soient dynamique ?????
 
par avance merci bcp  :sol:  :hello:  
 

Reply

Marsh Posté le 19-03-2007 à 16:58:49    

bin au lieu de 'c1' tu mets 'c'.$i ou i est l'itérateur de ta boucle [:spamafote]
Et pour la valeur pareil tu récupéres celle du tableau resultant du split qui va bien

Reply

Marsh Posté le 19-03-2007 à 17:14:11    

                       my $memoryfile = shift;                   # Array Reference to each open input file (mandatory)
                        my($line,$time,$key_hash,@dat,@fields);
                        %table_hash;
                        foreach $line (@memoryfile)
                        {
                                chomp($line);
                                if ($line !~ /^bscid/)
                                {
                                        # line : bscid,siteid,btsid,time,mcc,mnc,lac,ci,c1,c2,..,c(n)
                                        @fields = split(",",$line);
                                        $time = $fields[4];
                                        $time =~ s/^(\d{10})(\d{2})$/$1/;
                                        $heure = $2;
                                         
                                        if (($heure =~ /05/) || ($heure =~ /10/) || ($heure =~ /15/))
                                        {
                                                $heure = "00";
                                        }
                                        elsif (($heure =~ /20/) || ($heure =~ /25/) || ($heure =~ /30/))
                                        {
                                                $heure = "15";
                                        }
                                        elsif (($heure =~ /35/) || ($heure =~ /40/) || ($heure =~ /45/))
                                        {
                                                $heure = "30";
                                        }
                                        elsif (($heure =~ /50/) || ($heure =~ /55/) || ($heure =~ /00/))
                                        {
                                                $heure = "45";
                                        }
 
                                        $key_hash = "$fields[0]-$fields-[1]-$fields[2]-$fields[3]-$fields-[5]-$fields-[6]$fields[7]-$fields[8]";
 
 
                                        for ($i = 9; $i < 17; $i++) { $table_hash{$key_hash}{$heure}{'c'.$i} += $fields[$i]; }
                                }
                        }
 
 
exact ??? :sol:

Reply

Marsh Posté le 19-03-2007 à 17:14:11   

Reply

Marsh Posté le 19-03-2007 à 17:28:15    

sauf que du coup tu te retrouves avec C9 - C17 dans ta clé alors que tu cherches C1- C9; ça donne plus:

Code :
  1. $table_hash{$key_hash}{$heure}{'c'.($i-8)} += $fields[$i];
 

Attention maintenant tu joues avec un hash (clé $key_hash) de référence de hash ( clé heure) de référence de hash ( clé CN). Il faut que tu mettes des fleches au bon endroit et que tu penses à initialiser tes références si elles n'existe nt pas:

Code :
  1. ...
  2. $heure = $2;
  3. $table_hash{$key_hash} = {} if ! defined $table_hash{$key_hash};
  4. $table_hash{$key_hash}->{$heure} = {} if ! defined $table_hash{$key_hash}->{$heure};
  5. for ($i=9; $i<17; $i++){
  6.   if ( ! defined $table_hash{$key_hash}{$heure}->{'c'.$i} ){
  7.     $table_hash{$key_hash}{$heure}->{'c'.$i} = $fields[$i];
  8.   } else {
  9.     $table_hash{$key_hash}{$heure}->{'c'.$i} += $fields[$i];
  10.   }
  11. }


un peu verbeux mais au moins toutes les étapes sont bien décomposées


Message édité par anapajari le 19-03-2007 à 17:29:04
Reply

Marsh Posté le 19-03-2007 à 17:58:03    

pour le c9 - c17 ok mais cela ne me gène pas.
 

Code :
  1. my $memoryfile = shift;                   # Array Reference to each open input file (mandatory)
  2.                         my($line,$time,$key_hash,$i,$heure,$fields,@dat,@fields);
  3.                         %table_hash;
  4.                         while (@{$memoryfile}) {
  5.                                 $line = shift @{$memoryfile}; # Get line
  6.                                 chomp($line);
  7.                                 if ($line !~ /^bscid/)
  8.                                 {
  9.                                         # line : bscid,siteid,btsid,time,mcc,mnc,lac,ci,c1,c2,..,c(n)
  10.                                         @fields = split(",",$line);
  11.                                         $time = $fields[4];
  12.                                         $time =~ s/^(\d{10})(\d{2})$/$1/;
  13.                                         $heure = $2;
  14.                                         if (($heure =~ /05/) || ($heure =~ /10/) || ($heure =~ /15/))
  15.                                         {
  16.                                                 $heure = "00";
  17.                                         }
  18.                                         elsif (($heure =~ /20/) || ($heure =~ /25/) || ($heure =~ /30/))
  19.                                         {
  20.                                                 $heure = "15";
  21.                                         }
  22.                                         elsif (($heure =~ /35/) || ($heure =~ /40/) || ($heure =~ /45/))
  23.                                         {
  24.                                                 $heure = "30";
  25.                                         }
  26.                                         elsif (($heure =~ /50/) || ($heure =~ /55/) || ($heure =~ /00/))
  27.                                         {
  28.                                                 $heure = "45";
  29.                                         }
  30.                                         $key_hash = "$fields[0]-$fields-[1]-$fields[2]-$fields[3]-$fields-[5]-$fields-[6]$fields[7]-$fields[8]";
  31.                                         $table_hash{$key_hash} = {} if ! defined $table_hash{$key_hash};
  32.                                         $table_hash{$key_hash}->{$heure} = {} if ! defined $table_hash{$key_hash}->{$heure};
  33.                                         for ($i=9; $i<17; $i++){
  34.                                                  if ( ! defined $table_hash{$key_hash}{$heure}->{'c'.$i} ){
  35.                                                         $table_hash{$key_hash}{$heure}->{'c'.$i} = $fields[$i];
  36.                                                 } else {
  37.                                                         $table_hash{$key_hash}{$heure}->{'c'.$i} += $fields[$i];
  38.                                                 }
  39.                                         }
  40.                                 }
  41.                         }


 
lors de la compilation j'ai les messages :
 
Perl error: Global symbol "%table_hash" requires explicit package name at ********** line 74.
Global symbol "%table_hash" requires explicit package name at ********* line 107.
 
edit : merci encore pour ton aide, je dois y alelr.
 
J'espère à demain si j'ai encore des questions...


Message édité par steve419 le 19-03-2007 à 18:00:51
Reply

Marsh Posté le 19-03-2007 à 18:00:25    

euh veut bien t'aider mais la c'est de l'erreur ou si tu t'en sors pas autant allez elever des ratons laveurs.
Y'a quoi ligne 74 dans ton truc ( allez, sur ton bout de code ci-dessus, à mon avis ça doit être la ligne 3)? Tu vois pas comme un truc qui manque?

Reply

Marsh Posté le 19-03-2007 à 18:01:44    

je ne sais pas comment déclarer la table de hash  :sarcastic:

 

edit : avec le my ok !!!

 

il me reste plus qu'a coder la boucle pour reconstituer l'input !!!

Message cité 1 fois
Message édité par steve419 le 19-03-2007 à 18:04:30
Reply

Marsh Posté le 19-03-2007 à 18:11:45    

                       # Update the Input file with the pre-parsed data
                        foreach $cle (keys (%table_hash))
                        {
                                $line = $table_hash{$cle} ;
                        }
 
                        push @dat, $cle , $line;
 
                        @{$memoryfile} = @dat;

Reply

Marsh Posté le 19-03-2007 à 18:40:15    

steve419 a écrit :

je ne sais pas comment déclarer la table de hash  :sarcastic:


cherche feignasse ...  :fou:

steve419 a écrit :

edit : avec le my ok !!!


tu vois quand tu veux...

steve419 a écrit :

il me reste plus qu'a coder la boucle pour reconstituer l'input !!!


et ouais y'a plus qu'a ...

 
steve419 a écrit :

# Update the Input file with the pre-parsed data
                        foreach $cle (keys (%table_hash))
                        {
                                $line = $table_hash{$cle} ;
                        }
                        push @dat, $cle , $line;
                       @{$memoryfile} = @dat;

 

Nan mais la t'es gentil, tu ressors un vieux bout de code de je sais pas où, sans même avoir essayer de l'adapter à la hash préalablement construite...

 


Message édité par anapajari le 19-03-2007 à 18:40:50
Reply

Marsh Posté le 19-03-2007 à 21:06:18    

ok pour le vieu bout de code... :??:  :lol:  
 
je vais voir ça demain...
 
en espérant ne pas avoir perdu de vu mon professeur :hello:  
 
encore merci
 
@ deux mains :sarcastic:

Reply

Marsh Posté le 20-03-2007 à 16:27:56    

merci à anapajari, j'ai terminé, avec en plus des bouts de code pour durcir le traitement (traitement des cas particulier)
 
@+

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed