IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Perl Discussion :

valeurs d'un array


Sujet :

Langage Perl

  1. #1
    Membre éprouvé
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 45
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Par défaut valeurs d'un array
    comment afficher la plus petite valeur d'un array ainsi que son indice?

    merci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print @{ sort {$a<=>$b} @{$GC_segments{$id} }[0];

  2. #2
    Membre éprouvé
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 45
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Par défaut une solution
    une solution avec List::MoreUtils

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	my $min = (minmax ( @{$GC_segments{$id}} ))[0];
    	my @x = indexes { $_  == $min } @{$GC_segments{$id}};

  3. #3
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 822
    Par défaut
    ou tout simplement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #!/usr/bin/perl
    use warnings;
    use strict;
     
    my @test = qw/ 1 6  2 365 4 0 06 6 8 76 055 46 0 065 456 40 -5  95 4 05 400 564  4 469 6/;
    my ($index, $min);
    for my $i ( 0..$#test ) {
      if ( ( defined $min and $test[$i] < $min ) || not defined $min ) { 
        $index = $i; $min = $test[$i]; 
      }
    }
    print "Index : $index, Min : $min\n";
    Cela t'évite de parcourir le tableau plus d'une fois.

  4. #4
    Membre éprouvé
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 45
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Par défaut
    ok, merci

  5. #5
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Par défaut
    Pour le minimum, la fonction min de List::Util est largement suffisante.
    Pour ce qui est de trouver son indice, la fonction indexes rempli bien cet usage.
    Dans tous les cas, la complexité (donc le temps d'exécution) sera moindre que la solution du sort.

    Une astuce cependant pour exécuter une seule opération et récupérer l'indice (donc la valeur) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      my $min_idx = reduce { $table[$a] < $table[$b] ? $a : $b } 0..@table-1;
    Cela dit, cette solution ne retourne qu'un seul minimum.
    Pour obtenir plusieurs minimums, ta solution me semble la meilleure, même si l'on peut éviter la double boucle sur tous les éléments, mais en développant un peu le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
      my @min_idx = ();
      my $min = $table[0];
      foreach my $idx (1..@table-1) {
        if ($table[$idx] < $min) {
          @min_idx = ($idx);
          $min = $table[$idx];
        }
        elsif ($table[$idx] == $min) {
          push @min_idx, $idx;
        }
      }
    Résultat de profilage des 3 solutions suivantes (lire la colonne CumulS) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    #!/usr/bin/perl
    use 5.10.0;
    use List::Util qw(min max reduce);
    use List::MoreUtils qw(indexes minmax);
     
    my $size = $ARGV[0] // 100000;
    my @table = (map int(rand($size)), 1 .. $size);
     
    sub min1 {
      my $min = min(@table);
      my @min_idx = indexes { $_ == $min } @table;
      return $min, @min_idx;
    }
     
    sub min2 {
      my $min_idx = reduce { $table[$a] < $table[$b] ? $a : $b } 0..@table-1;
     
      return $table[$min_idx], [$min_idx];
    }
     
    sub min3 {
      my @min_idx = ();
      my $min = $table[0];
      foreach my $idx (1..@table-1) {
        if ($table[$idx] < $min) {
          @min_idx = ($idx);
          $min = $table[$idx];
        }
        elsif ($table[$idx] == $min) {
          push @min_idx, $idx;
        }
      }
     
      return $min, @min_idx;
    }
     
    print "Min1: ", (join " at position ", map ref($_) ? (join ", ", @$_) : $_, min1()), "\n";
    print "Min2: ", (join " at position ", map ref($_) ? (join ", ", @$_) : $_, min2()), "\n";
    print "Min3: ", (join " at position ", map ref($_) ? (join ", ", @$_) : $_, min3()), "\n";
     
    my $loop = max(10, 10 ** (6-log($size)/log(10)));
    print "loop = $loop\n";
    foreach (2..1000) {
      min1();min2();min3();
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    $ perl -d:DProf min.pl 100000 && dprofpp -I | grep -E "min[0-9]|Time"
    Min1: 0 at position 33023
    Min2: 0 at position 33023
    Min3: 0 at position 33023
    loop = 10
    Total Elapsed Time = 299.4175 Seconds
      User+System Time = 291.1645 Seconds
    Inclusive Times
    %Time ExclSec CumulS #Calls sec/call Csec/c  Name
     52.6   0.415 153.32   1000   0.0004 0.1533  main::min1
     36.3   8.855 105.95   1000   0.0089 0.1060  main::min2
     10.9   31.81 31.811   1000   0.0318 0.0318  main::min3
     
    $ perl -d:DProf min.pl 10000 && dprofpp -I | grep -E "min[0-9]|Time"
    Min1: 0 at position 1390
    Min2: 0 at position 1390
    Min3: 0 at position 1390
    loop = 100
    Total Elapsed Time = 29.04515 Seconds
      User+System Time = 28.68215 Seconds
    Inclusive Times
    %Time ExclSec CumulS #Calls sec/call Csec/c  Name
     52.6   0.088 15.110   1000   0.0001 0.0151  main::min1
     36.4   0.949 10.464   1000   0.0009 0.0105  main::min2
     10.9   3.129  3.129   1000   0.0031 0.0031  main::min3
     
    $ perl -d:DProf min.pl 1000 && dprofpp -I | grep -E "min[0-9]|Time"
    Min1: 0 at position 331
    Min2: 0 at position 331
    Min3: 0 at position 331
    loop = 1000
    Total Elapsed Time = 2.876828 Seconds
      User+System Time = 2.846828 Seconds
    Inclusive Times
    %Time ExclSec CumulS #Calls sec/call Csec/c  Name
     51.9   0.009  1.479   1000   0.0000 0.0015  main::min1
     38.0   0.118  1.082   1000   0.0001 0.0011  main::min2
     10.8   0.310  0.310   1000   0.0003 0.0003  main::min3
     
    $ perl -d:DProf min.pl 100 && dprofpp -I | grep -E "min[0-9]|Time"
    Min1: 0 at position 17
    Min2: 0 at position 17
    Min3: 0 at position 17
    loop = 10000
    Total Elapsed Time = 0.353553 Seconds
      User+System Time = 0.342553 Seconds
    Inclusive Times
    %Time ExclSec CumulS #Calls sec/call Csec/c  Name
     53.7   0.027  0.184   1000   0.0000 0.0002  main::min2
     42.9   0.025  0.147   1000   0.0000 0.0001  main::min1
     4.09   0.014  0.014   1000   0.0000 0.0000  main::min3
    Pour des petits tableaux, bien sur, le profilage ne se justifie pas.

    Edit: grillé par djibril

Discussions similaires

  1. [Tableaux] Valeurs dans un Array..
    Par adrtk dans le forum Langage
    Réponses: 1
    Dernier message: 01/12/2007, 12h53
  2. Réponses: 2
    Dernier message: 14/08/2007, 16h18
  3. Réponses: 9
    Dernier message: 28/06/2006, 11h11
  4. Réponses: 2
    Dernier message: 28/03/2006, 11h45
  5. Réponses: 5
    Dernier message: 18/11/2005, 22h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo