Trier tableau - max en perl

Résolu
wafa_o Messages postés 109 Date d'inscription   Statut Membre Dernière intervention   -  
wafa_o Messages postés 109 Date d'inscription   Statut Membre Dernière intervention   -
Bonjour,

Je souhaite obtenir la 2ème valeur max d'un fichier.
Par exemple, j'ai le fichier suivant :
machine1 00:00 18
machine1 01:00 25
machine1 02:00 6
machine2 13:00 58
machine2 14:00 16
machine2 15:00 75

Je voudrais avoir le résultat suivant
machine1 01:00 18
machine2 14:00 58

J'ai essayé la commande my @tri = sort { $a->[2] <=> $b->[2] } @val; en ayant placé mes champs dans le tableau @val mais ca ne fonctionne pas.
Merci d'avance à ceux qui pourront m'aider.
A voir également:

17 réponses

lami20j
 
Salut,

Selon moi, il ne se produira pas.
Si tu le dis.

Essaie ça

lami20j@debian-vbox:/mnt/vbox/perl$ cat tri.pl 
#!/usr/bin/perl
use strict;use warnings;
my %h;
while(<DATA>){
  next if /^$/;
  my @t=split;
  push @{$h{$t[0]}}, join " ",@t[1..2];
}
for my $k(sort keys %h){
  my @t=map  { $_->[0] } 
        sort { $b->[2] <=> $a->[2] } 
	map  { [$_, split ] } 
	@{$h{$k}};
  print "$k $t[1]\n";
}
__END__
A 00:00 15
A 01:00 52
A 02:00 35
A 03:00 16
A 04:00 65
A 05:00 84
A 06:00 41

B 00:00 45
B 01:00 16
B 02:00 98
B 03:00 102
B 04:00 10
B 05:00 9
B 06:00 43

C 00:00 12
C 01:00 85
C 02:00 35
C 03:00 17
C 04:00 66
C 05:00 48
C 06:00 26

Le résultat
lami20j@debian-vbox:/mnt/vbox/perl$ perl tri.pl
A 04:00 65
B 02:00 98
C 04:00 66
1
lami20j
 
Salut,

Si je comprends bien tu ne veux pas toucher les 2 premières colonnes et trier seulement la 3ème?
0
wafa_o Messages postés 109 Date d'inscription   Statut Membre Dernière intervention   2
 
Oui c'est ca, je ne touche pas aux deux premières colonnes. Seulement à l'affichage je veux recuperer les valeurs des colonnes 1 et 2 qui correspondent à la valeur de la colonne 3.
0
lami20j
 
Re,

Tu as du te tromper puisque avant18 il y a 16
machine1 01:00 18
Ca doit être comme ça?
lami20j@debian:~$ cat tri.pl
#!/usr/bin/perl
use strict;use warnings;
my (@f,@t,@tri,@final);

while(<DATA>){
  push @f, [ (split /\s+/)[0..1] ];
  push @t,$1 if /\s(\d+)$/;
}

@tri = sort {$a <=> $b} @t;
print "@$_ ",shift @tri,"\n" for @f;
__END__
machine1 00:00 18
machine1 01:00 25
machine1 02:00 6
machine2 13:00 58
machine2 14:00 16
machine2 15:00 75
lami20j@debian:~$ perl tri.pl
machine1 00:00 6
machine1 01:00 16
machine1 02:00 18
machine2 13:00 25
machine2 14:00 58

machine2 15:00 75
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
wafa_o Messages postés 109 Date d'inscription   Statut Membre Dernière intervention   2
 
Euh, non ce n'était pas une erreur.
Je crois que ce n'était pas claire.

En fait je voudrais la seconde valeur max pour toutes les machines.

Exemple :

machine1 00:00 18
machine1 01:00 25
machine1 02:00 6
machine2 13:00 58
machine2 14:00 16
machine2 15:00 75

La 2nd valeur max de la machine 1 est 18 à 00:00
La 2nd valeur max de la machine 2 est 58 à 13:00

Résultat :
machine1 01:00 18
machine2 14:00 58


Je parlais de trie parce que c'est la première idée qui m'est venue à l'esprit pour obtenir le résultat.
0
lami20j
 
Re,


En fait je voudrais la seconde valeur max pour toutes les machines.
Je ne comprends pas.
Le champs de milieu ne compte pas?

machine1 00:00 18
machine1 01:00 25
machine1 02:00 6


Ici il y a une machine non?
Pourquoi machine1 01:00 18 et pas machine1 01:00 25 ou machine1 00:00 25
0
wafa_o Messages postés 109 Date d'inscription   Statut Membre Dernière intervention   2
 
Dans l'exemple donné, il y a deux machine1 et machine2.

Pour la machine 1 :
machine1 00:00 18
machine1 01:00 25
machine1 02:00 6

J'ai trois valeurs à des heures différentes. Je veux le 2ème max soit 18.
Pour la machine 1 j'ai la valeur 18 à 00:00.


Un autre exemple :
machine1 00:00 18
machine1 01:00 25
machine1 02:00 6
machine1 03:00 78
machine1 04:00 41
machine1 05:00 35

Dans ce cas là, le resultat doit être :
machine1 04:00 41


Tu comprends ?
0
lami20j
 
Re,

Non, je ne comprends pas ;-(

Pourquoi tu veux machine1 04:00 41 et pas machine1 05:00 41? C'est toujours la machine 1 non?

Je ne comprends pas ton raisonnement. Si je n'ai pas des critères claires je ne peux rien faire.
0
wafa_o Messages postés 109 Date d'inscription   Statut Membre Dernière intervention   2
 
Oui c'est toujours la machine1 mais c'est pas la même heure.
Je recupère la ligne entière où j'ai 41. Dans mon exemple, pour la valeur 41 à gauche j'ai 04:00 et machine1.

machine1 05:00 correspond à la valeur 35, pas 41.

C'est plus claire ;) ?
0
lami20j
 
Re,

Oui c'est toujours la machine1 mais c'est pas la même heure.
D'accord, mais en ce cas si l'heure compte, alors il n'y a rien à trier puisque l'heure ne correspond jamais dans ton exemple.

J'aurais compris si j'avais
machine1 01:00 15
machine1 01:00 25

et que tu veux obtenir
machine 01:00 25
0
wafa_o Messages postés 109 Date d'inscription   Statut Membre Dernière intervention   2
 
Salut

Le trie était mon idée de départ, c'est certainement pour ca que je n'y arrivais pas.
Est ce que tu as des pistes à me suggérer ?
0
lami20j
 
Salut,

Je te propose de me donner un exemple concret (avec plusieurs machines et plusieurs heures) de ce que tu veux et je m'en occuperai, puisque je n'ai pas compris ce que tu veux obtenir. Tant que je ne comprends pas je ne peux rien faire ;-(
0
wafa_o Messages postés 109 Date d'inscription   Statut Membre Dernière intervention   2
 
Ok, merci.
J'ai appelé les machines A, B, C. Ce sera plus lisible j'espère.

Alors un exemple d'un fichier avec le contenu :
Colonne 1 Colonne 2 Colonne 3
A 00:00 15
A 01:00 52
A 02:00 35
A 03:00 16
A 04:00 65
A 05:00 84
A 06:00 41

B 00:00 45
B 01:00 16
B 02:00 98
B 03:00 102
B 04:00 10
B 05:00 9
B 06:00 43

C 00:00 12
C 01:00 85
C 02:00 35
C 03:00 17
C 04:00 66
C 05:00 48
C 06:00 26


Et le résultat que je souhaite est :
A 04:00 65
B 02:00 98
C 04:00 66

Il y a 3 colonnes. La colonne 1 représente les machines. Dans l'exemple il y en a 3 (A, B et C)
Prenons le cas de la machine A.
A différentes heures (colonne 2), la machine A a réalisé un certain nombre de pièces (colonne 3).

Je voudrais afficher pour chaque machine:
- Le nom de la machine en question
- l'heure à laquelle elle a réalisé X pièces (X étant la 2ème valeur max de pièce).
- la valeur X

(Par exemple, pour A en ordre croissant de valeur j'aurai :
A 00:00 15
A 03:00 16
A 02:00 35
A 06:00 41
A 01:00 52
A 04:00 65 <==
A 05:00 84
Je récupére l'avant dernière ligne. (65 étant le 2ème max). J'affiche donc A 04:00 65)

J'espère vraiment avoir été plus claire.
0
lami20j
 
Re,

Ok, c'est plus clair.

Reste un bémol quand même.
Si on a deux valeurs pour le second max on choisi lequel?

Par exemple
A 00:00 15
A 03:00 16
A 02:00 65 <==
A 06:00 41
A 01:00 52
A 04:00 65 <==
A 05:00 84 

Il faudra peut être penser à utiliser un critère multiple de tri? Par heure par exemple.
0
wafa_o Messages postés 109 Date d'inscription   Statut Membre Dernière intervention   2
 
A vrai dire, le cas ne s'est jamais présenté. Selon moi, il ne se produira pas.
0
lami20j
 
Re,

En fait ça marche sans utiliser le tableau @t, un mais map-sort-map dans un contexte de liste et on affiche le deuxième élément.

lami20j@debian-vbox:/mnt/vbox/perl$ cat tri.pl 
#!/usr/bin/perl
use strict;use warnings;
my %h;
while(<DATA>){
  next if /^$/;
  my @t=split;
  push @{$h{$t[0]}}, join " ",@t[1..2];
}
for my $k(sort keys %h){
  print "$k ",
	(map  { $_->[0] } 
        sort { $b->[2] <=> $a->[2] } 
	map  { [$_, split ] } 
	@{$h{$k}})[1]
	,"\n";
}
__END__
A 00:00 15
A 01:00 52
A 02:00 35
A 03:00 16
A 04:00 65
A 05:00 84
A 06:00 41

B 00:00 45
B 01:00 16
B 02:00 98
B 03:00 102
B 04:00 10
B 05:00 9
B 06:00 43

C 00:00 12
C 01:00 85
C 02:00 35
C 03:00 17
C 04:00 66
C 05:00 48
C 06:00 26
0
wafa_o Messages postés 109 Date d'inscription   Statut Membre Dernière intervention   2
 
Salut,

Merci. Je viens de tester et ca fonctionne parfaitement.
0