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];
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];
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}};
ou tout simplement :
Cela t'évite de parcourir le tableau plus d'une fois.
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";
- Les meilleurs cours et tutoriels Perl et Perl 6 pour vous former ;
- FAQ Perl, Perl 6 et Perl/Tk d'entraide ;
- Les news sur la rubrique Perl ;
- S'abonner au compte Twitter de la rubrique Perl ;
- Mes tutoriels developpez.com.
Pas de questions technique par messagerie privée (lisez les règles du forum Perl) et pour les nouveaux !
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) :
Cela dit, cette solution ne retourne qu'un seul minimum.
Code : Sélectionner tout - Visualiser dans une fenêtre à part my $min_idx = reduce { $table[$a] < $table[$b] ? $a : $b } 0..@table-1;
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 :
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 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; } }
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(); }Pour des petits tableaux, bien sur, le profilage ne se justifie pas.
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
Edit: grillé par djibril
Partager