Hash et somme

debousole Messages postés 4 Date d'inscription   Statut Membre Dernière intervention   -  
 Pat -
Bonjour,

J'ai un tableau ne contenant que des 1 et 0. Il est possible d'avoir 2 fois le même éléments. Je souhaiterai avoir chaque élément qu'une seule fois et faire la somme de chaque colonne et remplacer quand la somme de la colonne est égale à 2 indiquer 1.

tableau initial :
element1 1 0 1
element2 0 1 1
element3 1 1 0
element1 0 0 1

tableau final:
element1 1 0 1
element2 0 1 1
element3 1 1 0


Si quelqu'un peux m'aider s'il vous plaît, je "patauge" depuis un moment merci
my $fichier = 'exemple';

open my $fh, '<', $fichier or die "Impossible de lire le fichier $fichier\n";

my %data;
my $i=0;
my $j=0;


while(my $ligne = <$fh>){
 $i++;
 chomp $ligne;
 if($ligne =~ /gene.*/){
  $j++;
  my ($gene,$champ1,$champ2,$champ3) = split "\t", $ligne;
  my $element =$champ1."\t".$champ2."\t".$champ3;
  push @{$data{$gene}}, [$element];
 }
}

for my $id (keys %data) {
 my @array = @{$data{$id}};
 $data{$id} = \@array;
}
#print Dumper \%data; #ok bonne vérif


for my $id (keys %data) {
 print "--$id\n";
 my @tableau=();
 my @array = @{$data{$id}};


 for my $pair (@array) { 
  #print ("\t$pair->[0]\n");#ok bonne vérif

  #faire la somme de chaque colonne 
  my @hit = split("\t",$pair->[0]);

  for (my $m = 0; $m < @hit ; $m++) {
   print "colonne $m - valeur $hit[$m]\n";
  }
 }
}
close($fh);

Configuration: Linux / Firefox 68.0

3 réponses


 
Salut,

Il ne peut y avoir qu'une répétition d'élément, selon ce que je comprends, et il y a toujours 3 colonnes de données pour chaque élément ?

Si oui, j'aurai fait plus simple avec une regexp et un hash de tableaux :

#!/usr/bin/perl
  
use strict;
use warnings;

my %data;

while (<DATA>) {
    if (/(element\d+)\s+(\d)\s+(\d)\s+(\d)/) {
        # la ligne matche et nous avons capturé les 4 données
        if (!$data{$1}) {
            # si l'élément n'est pas déjà stocké dans le hash, on crée l'entrée
            $data{$1} = [$2, $3, $4];
        } else {
            # si l'élément est déjà stocké dans le hash, on retraite les données
            $data{$1} = [ 
                $2 + $data{$1}[0] == 2 ? 1 : $2 + $data{$1}[0],
                $3 + $data{$1}[1] == 2 ? 1 : $3 + $data{$1}[1],
                $4 + $data{$1}[2] == 2 ? 1 : $4 + $data{$1}[2]
            ];
        }
    }
}

# affichage ordonné par clef
foreach my $elem (sort keys %data) {
    print "$elem\t$data{$elem}[0]\t$data{$elem}[1]\t$data{$elem}[2]\n";
}

__END__
element1    1   0   1
element2    0   1   1
element3    1   1   0
element1    0   0   1

donne sur ton jeu de données :

$ perl 36867025.pl
element1 1 0 1
element2 0 1 1
element3 1 1 0



Dal
0
Pat
 
Bien joué BRAVO
0
debousole Messages postés 4 Date d'inscription   Statut Membre Dernière intervention  
 
Merci bien.
Oui Il ne peut y avoir qu'une répétition d'élément,
J'ai 20 colonnes, en fait il y a toujours un nombre fixe de colonnes de donnée pour chaque élément

Ah oui nettement plus simple...

J'ai avancé et trouvé une solution (sauf pour le remplacement de 2 par 1, un sed après traitement au pire)

open my $fh, '<', $fichier or die "Impossible de lire le fichier $fichier\n";

my %data;
my $i=0;
my $j=0;

while(my $ligne = <$fh>){
$i++;
chomp $ligne;
if($ligne =~ /gene.*/){
$j++;
my ($gene,$champ1,$champ2,$champ3) = split "\t", $ligne;
my $element =$champ1."\t".$champ2."\t".$champ3;
push @{$data{$gene}}, [$element];
}
}
for my $id (keys %data) {
my @array = @{$data{$id}};
$data{$id} = \@array;
}
#print Dumper \%data;

for my $id (keys %data) {
print "--$id\n";
my @tableau=();
my @array = @{$data{$id}};

my @sums;
for my $pair (@array) {
print ("\t$pair->[0]\n");

#faire la somme de chaque colonne quand la somme est égale à 2 remplacer par 1
my @nums = split("\t",$pair->[0]);
my $o = 0;
foreach my $num (@nums){
$sums[$o] += $num;
$o += 1;
}
}
print"=>\t";
foreach my $sum (@sums){
print("$sum\t");
}
print"\n";
}




Encore MERCI
0
debousole Messages postés 4 Date d'inscription   Statut Membre Dernière intervention  
 
MERCI beaucoup!
Oui mon script est basé sur 3 colonnes pour que je puisse vérifier mon script rapidement...
0