Formater des données

Formater des données - Perl - Programmation

Marsh Posté le 09-06-2010 à 19:49:46    

Bonjour,
 
je débute en programmation perl et voila mon problème je possède un grand nombre de fichiers qui sont de cette forme :
 
4344222
2141221
4121221
 
Et pour chaque colonne je dois remplacer le chiffre majeur par 1 et par 2 le mineur ce qui donne ça à la fin :
 
1212112
2111111
1121111
 
Quand il y a égalité ou que le caractère est le même il suffit de mettre 1 par defaut.
 
Pourriez vous m'aider ?
 
Merci d'avance

Reply

Marsh Posté le 09-06-2010 à 19:49:46   

Reply

Marsh Posté le 09-06-2010 à 23:36:02    

Bonjour,
Le nombre de lignes et de colonnes de tes fichiers est il toujours le même, ou bien est-ce variable, et en ce cas, les valeurs moyennes de ces nombres tournent autour de combien?
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 10-06-2010 à 09:44:39    

Bonjour,
 
C'est variable je peux par exemple avoir 8 lignes c'est rarement plus mais je peux avoir 200 colonnes.
 
Merci

Reply

Marsh Posté le 10-06-2010 à 14:58:00    

OK, bon ben je vais regarder ça.
Il y a peut être moyen de faire ça via la librairie PDL de perl, mais comme je ne connais pas bien cette librairie, je vais regarder directement.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 11-06-2010 à 11:16:10    

chandlerbing87 a écrit :

Bonjour,

 

je débute en programmation perl et voila mon problème je possède un grand nombre de fichiers qui sont de cette forme :

 

4344222
2141221
4121221

 

Et pour chaque colonne je dois remplacer le chiffre majeur par 1 et par 2 le mineur ce qui donne ça à la fin :

 

1212112
2111111
1121111

 

Quand il y a égalité ou que le caractère est le même il suffit de mettre 1 par defaut.

 

Pourriez vous m'aider ?

 

Merci d'avance

sauf que le tableau résultat que tu donnes est faux, rien que pour la 2e colonne, 3 etant le chiffre majeur, on devrait avoir 1 en tête de colonne et non 2. etc.
Un exemple qui devrait marcher:

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. #a appeler avec: perl monscript.pl fichier-de-données
  6. my $filename = shift;
  7. open my $input, '+<', $filename or die "Impossible d'ouvrir le fichier $filename :$!";
  8. my $line;
  9. my @row;
  10. my @min;
  11. my @max;
  12. my $cnt = 0;
  13. while ($line = <$input> ) {
  14.    chomp($line);
  15.    next if $line =~ /^\s*$/;
  16.    @row = split (//, $line);
  17.    if ($cnt) {
  18.        map { if ($row[$_] < $min[$_]) {$min[$_] = $row[$_]};
  19.              if ($row[$_] > $max[$_]) {$max[$_] = $row[$_]}; } 0 .. $#row;
  20.    }
  21.    else {
  22.        #first line
  23.        @min = @row;
  24.        @max = @row;
  25.        $cnt++;
  26.    }
  27. }
  28. seek($input, 0, 0);
  29. while ($line = <$input> ) {
  30.    chomp($line);
  31.    next if $line =~ /^\s*$/;
  32.    @row = split (//, $line);
  33.    map { if ($row[$_] == $max[$_]) {$row[$_] = 1}
  34.          else { if ($row[$_] == $min[$_]) {$row[$_] = 2}}
  35.      } 0 .. $#row;
  36.    print join("", @row),"\n";
  37.  
  38. }
  39. close ($input);


On fait une première passe et on range le min et max de chaque colonne dans un tableau, puis on fait une seconde passe, et on substitue par 1 ou 2 si nécessaire.
A+,


Message édité par gilou le 11-06-2010 à 11:18:29

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 11-06-2010 à 13:57:10    

Merci beaucoup pour ton script c'est vraiment top. J'ai lu que tu me disais que mon résultat était faux en fait je me suis mal exprimé ce que j'entendais pas caractère majoritaire c'était juste le caractère qui était le plus présent dans une colonne, c'est à dire si 1 est présent 3 fois et 4 présent 1 fois le caractère majoritaire est 1 et le minoritaire est 4. En clair je parlais du nombre d'occurence et non de la valeur propre.
 
Merci vraiment beaucoup  

Reply

Marsh Posté le 11-06-2010 à 14:19:29    

OK! dans ce cas la, il faut changer complètement de qui est fait dans la première passe.
Je vais y jeter un œil.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 11-06-2010 à 15:06:28    

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. use List::Util qw(min max);
  6.  
  7. #a appeler avec: perl monscript.pl fichier-de-données
  8. my $filename = shift;
  9. open my $input, '+<', $filename or die "Impossible d'ouvrir le fichier $filename :$!";
  10. my $line;
  11. my @row;
  12. my @aoh; #array of hashes
  13. while ($line = <$input> ) {
  14.    chomp($line);
  15.    next if $line =~ /^\s*$/;
  16.    @row = split (//, $line);
  17.    map {$aoh[$_]{$row[$_]}++;} 0 .. $#row;
  18. }
  19. my @min = map {min values %{$aoh[$_]}} 0 .. $#aoh;
  20. my @max = map {max values %{$aoh[$_]}} 0 .. $#aoh;
  21. seek($input, 0, 0);
  22. while ($line = <$input> ) {
  23.    chomp($line);
  24.    next if $line =~ /^\s*$/;
  25.    @row = split (//, $line);
  26.    map { if ($aoh[$_]{$row[$_]} == $max[$_]) {$row[$_] = 1}
  27.          else { if ($aoh[$_]{$row[$_]} == $min[$_]) {$row[$_] = 2}}
  28.      } 0 .. $#row;
  29.    print join("", @row),"\n";
  30.  
  31. }
  32. close ($input);


La en sortie sur ton exemple, ca donne la même chose que pour ton post initial.
C'était juste un peu plus complexe:
En phase 1, on a un tableau qui pour chaque colonne, a un hash qui a chaque chiffre associe son nombre d'occurrences.
Une fois cela fait, on calcule pour chaque colonne l'occurrence min et max et on en fait deux tableaux.
En phase 2, pour un chiffre, on compare son occurence avec l'occurence maximale dans la colonne, si c'est la même, on remplace par 1, etc.
A+,


Message édité par gilou le 11-06-2010 à 15:11:28

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 11-06-2010 à 19:02:13    

Merci vraiment beaucoup!!!

Reply

Marsh Posté le 01-07-2010 à 10:04:14    

J'ai encore besoin de ton aide gilou.
 
En fait au lieu de mettre 1 par défaut quand il y a autant de max que de min, il faudrait mettre 1 pour le max et 2 pour le min même si il y a égalité.
 
En fait si on a :
 
4
3
4
3  
 
avoir :
 
1  ou 2
2      1
1      2
2      1
 
Merci d'avance
 
 

Reply

Marsh Posté le 01-07-2010 à 10:04:14   

Reply

Marsh Posté le 01-07-2010 à 13:46:02    

Mais tu fais quoi avec le cas suivant:
5
4
3
5
4
3
??
A+,


Message édité par gilou le 01-07-2010 à 13:46:39

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 01-07-2010 à 14:07:54    

En fait je peux pas avoir plus de 2 caractères différents.

Reply

Marsh Posté le 01-07-2010 à 16:26:14    

A priori, ceci devrait coller

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. use List::Util qw(min max);
  6.  
  7. #a appeler avec: perl monscript.pl fichier-de-données
  8. my $filename = shift;
  9. open my $input, '+<', $filename or die "Impossible d'ouvrir le fichier $filename :$!";
  10. my $line;
  11. my @row;
  12. my @aoh; #array of hashes
  13. while ($line = <$input> ) {
  14.    chomp($line);
  15.    next if $line =~ /^\s*$/;
  16.    @row = split (//, $line);
  17.    map {$aoh[$_]{$row[$_]}++;} 0 .. $#row;
  18. }
  19. my @max = map {max values %{$aoh[$_]}} 0 .. $#aoh;
  20. my @min = map {min values %{$aoh[$_]}} 0 .. $#aoh;
  21.  
  22. #En entrée, un array de hashs chaque hash est une liste de (caractere, nb d'occurences dans la colonne)
  23. #En sortie, un array de hashs chaque hash est une liste de (caractere, 2 ou 1)
  24. #Noter que ca ne marche que parce qu'il y a seulement au plus deux caractères distincts par colonne
  25. foreach (0 .. $#aoh) {
  26.    my $firstkey = (keys %{$aoh[$_]})[0];
  27.    my $firstval = ${$aoh[$_]}{$firstkey};
  28.    my $maxi = $max[$_];
  29.    if ($max[$_] == $min[$_]) {
  30.        foreach my $key (keys %{$aoh[$_]}) {
  31.            if ($key == $firstkey) {
  32.                ${$aoh[$_]}{$key} = 1;
  33.            }
  34.            else {
  35.                ${$aoh[$_]}{$key} = 2;
  36.            }
  37.        }
  38.    }
  39.    else {
  40.        foreach my $key (keys %{$aoh[$_]}) {
  41.            if (${$aoh[$_]}{$key} == $maxi) {
  42.                ${$aoh[$_]}{$key} = 1;
  43.            }
  44.            else {
  45.                ${$aoh[$_]}{$key} = 2;
  46.            }
  47.        }
  48.    }
  49. }
  50.  
  51. seek($input, 0, 0);
  52. while ($line = <$input> ) {
  53.      chomp($line);
  54.      next if $line =~ /^\s*$/;
  55.      @row = split (//, $line);
  56.      map { $row[$_] = ${$aoh[$_]}{$row[$_]}
  57.        } 0 .. $#row;
  58.      print join("", @row),"\n";
  59.  
  60. }
  61. close ($input);


Il y a probablement plus simple, mais faut pas trop en demander par 32 degrés à l'ombre.

 

A+,


Message édité par gilou le 01-07-2010 à 16:40:10

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 09-07-2010 à 10:18:58    

Pardonne moi pour cette réponse tardive, mais merci beaucoup !!!!

Reply

Sujets relatifs:

Leave a Replay

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