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 :

[langage] tri de fichier


Sujet :

Langage Perl

  1. #1
    Candidat au Club
    Inscrit en
    Avril 2003
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 3
    Points : 4
    Points
    4
    Par défaut [langage] tri de fichier
    Bonjour,
    Débutant en perl je cherche à faire 2 tris à partir d'un fichier d'origine.

    Le zonage du fichier est le suivant:
    PAYS;REGION;VILLE;POPULATION

    Dans le premier cas un tri avec plusieurs critères .
    clé primaire : le PAYS
    clé secondaire : la REGION
    Dans le second cas avec un seul critère.
    clé primaire : la Population
    Merci à toute personne pouvant m'aider à comprendre la méthode qui va me permettre de résoudre mon problème.
    Cordialement.
    JJ

  2. #2
    Membre expert
    Avatar de 2Eurocents
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    2 177
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 2 177
    Points : 3 166
    Points
    3 166
    Par défaut
    Bonsoir,

    Eh bien, si tout ton fichier peut tenir en mémoire, cela devient un problème assez trivial pour Perl :

    Il suffit de le charger dans un tableau ou une table de hachage, puis d'appliquer le tri en utilisant un bloc d'instruction spécifique, ainsi, par exemple :

    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
    #!/usr/bin/perl -w
    use strict;
     
    my @lignes;
    my $elements;
     
    print "Lecture du fichier\n";
    open (INPUT, "<villes.txt");
    while (<INPUT>) {
      chomp $_;
      # Eclatage des éléments de lignes dans une liste dont on prend la référence
      $elements = [ split /;/, $_ ];
      # Et ajout de cette référence dans notre tableau
      push (@lignes, $elements);
    }
    close (INPUT);
     
    print "Tri par population\n";
    # On trie les indices de notre tableau selon le 4e element de celui ci (pop.)
    my @tri_population = sort { $lignes[$a][3] <=> $lignes[$b][3] } (0..@lignes-1);
    # Affichage des noms (3e element) dans l'ordre du tri
    foreach my $index (@tri_population) {
      print $lignes[$index][2]."\n";
    }
     
    print "Tri par pays/region\n";
    # On trie les indices de notre tableau selon les 1er et 2e elements (pays/region)
    # Si les pays sont différents -> tri par pays
    # Si les pays sont identiques, tri par région
    my @tri_paysregion = sort { if ($lignes[$a][0] ne $lignes[$b][0]) {
                                  ($lignes[$a][0] cmp $lignes[$b][0])
                                } else {
                                  if ($lignes[$a][1] ne $lignes[$b][1]) {
                                    ($lignes[$a][1] cmp $lignes[$b][1])
                                  } else {
                                    ($lignes[$a][2] cmp $lignes[$b][2])
                                  }
                                } } (0..@lignes-1);
    # Affichage des noms (3e element) dans l'ordre du tri
    foreach my $index (@tri_paysregion) {
      print $lignes[$index][2]."\n";
    }
    Dans le second bloc de tri, j'en ai même ajouté un selon le nom de la ville.

    Ce n'est qu'un exemple. Les choses peuvent encore être améliorées.

    Bon courage.
    La FAQ Perl est par ici
    : La fonction "Rechercher", on aurait dû la nommer "Retrouver" - essayez et vous verrez pourquoi !

  3. #3
    Membre expert
    Avatar de 2Eurocents
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    2 177
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 2 177
    Points : 3 166
    Points
    3 166
    Par défaut
    Citation Envoyé par 2Eurocents
    Les choses peuvent encore être améliorées.
    Comme par exemple en remplaçant le bloc personnalisé du second sort par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    my @tri_paysregion = sort { ($lignes[$a][0] cmp $lignes[$b][0]) ||
                                ($lignes[$a][1] cmp $lignes[$b][1]) ||
                                ($lignes[$a][2] cmp $lignes[$b][2])
                              } (0..@lignes-1);
    C'est plus joli, non ?
    La FAQ Perl est par ici
    : La fonction "Rechercher", on aurait dû la nommer "Retrouver" - essayez et vous verrez pourquoi !

  4. #4
    Candidat au Club
    Inscrit en
    Avril 2003
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 3
    Points : 4
    Points
    4
    Par défaut tri de fichier
    Merci pour la solution que je vais tenter de décoder pour comprendre et savoir pour la prochaine fois

  5. #5
    Membre expert
    Avatar de 2Eurocents
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    2 177
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 2 177
    Points : 3 166
    Points
    3 166
    Par défaut
    Pour le décodage, voici une lecture commentée :

    ligne 8 -> Ouverture du fichier en lecture

    ligne 9 -> Boucle de lecture du fichier, tant qu'il y a quelquechose dedans. Le résultat de la lecture (ligne lue) est dans la variable interne $_

    ligne 10 -> On retire le saut de ligne qui se trouve à la fin de $_

    ligne 12 -> On éclate la ligne, selon le séparateur de champs ";", et la liste ainsi obtenue est mise dans un tableau anonyme dont on récupère la référence dans la variable $elements.

    ligne 14 -> La référence $element est ajoutée à la liste @lignes (qui est donc, du coup, un tableau de tableaux)

    ligne 16 -> On ferme le fichier. Fin des préliminaires. Nous allons passer à l'action.

    ligne 20 -> Tri selon la population (4e element de liste, indice 3).
    J'ai pris l'option de conserver le tableau @lignes inchangé, ce qui complique un peu la tâche mais permet de voir des constructions interessantes.
    Ce que je trie, c'est une liste des indices du tableau.
    Cette liste va de 0 au nombre d"éléments du tableau moins un, soit, avec la génération par l'opérateur .. : 0..@lignes-1
    Les variables internes $a et $b contiennet donc les indices d"éléments en cours de tri. On va comparer numériquement (<=>) les 4e elements des tableaux d'indices $a et $b.

    lignes 22 à 24 -> On affiche ce qu'on a trié, parce qu'on est fier d'y être arrivé 8)

    Lignes 30 à 33 (ou 38, selon la version des tests) -> rebelote, un tri, mais on enchaine les condition pour trier successivement selon les différents critères.
    La première version est plus longue mais je la trouve plus facile à comprendre : Si les valeurs d'un critère sont différentes, on trie selon ce critère, sinon, on descend au critère du dessous et on fait le même genre de test ...
    Le fonctionnement de la deuxième version est un peu mystérieux pour moi ... comment l'opérateur || se débrouille avec les valeurs -1, 0 et 1 retournées par les opérateurs <=> et cmp (comparaison lexicographique) ? plutôt bien, mais de quelle façon ???

    Voila, en espérant que ça t'aide à aller plus loin ...
    La FAQ Perl est par ici
    : La fonction "Rechercher", on aurait dû la nommer "Retrouver" - essayez et vous verrez pourquoi !

  6. #6
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Le fonctionnement de la deuxième version est un peu mystérieux pour moi ... comment l'opérateur || se débrouille avec les valeurs -1, 0 et 1 retournées par les opérateurs <=> et cmp (comparaison lexicographique) ? plutôt bien, mais de quelle façon ???
    Comme dans tous les langages modernes (et même anciens !) le or (ou ||) est un opérateur dit à court-circuit, autrement dit, dès que la valeur finale de l'opérateur peut-être déterminé, il arrète d'évaluer ses opérandes : exemple :
    1 || print "Hello";
    Le premier opérande est 1 (donc une valeur vraie), donc la valeur totale du ou est vraie... (1 ou 0, 0 ou 1, 1 ou 1 sont tous vrais) Le || arrête là son calcul, et n'évalue pas son deuxième opérande, donc "Hello" n'est jamais affiché par cette portion du code.
    0 || print "Hello";
    A contrario, ici "Hello" est toujours affiché...

    Il faut savoir par ailleurs que || ne renvoit pas vrai ou faux, mais la valeur de son premier opérande qui est considéré comme vrai. D'où le comportement observé ici !

    --
    Jedaï

  7. #7
    Membre expert
    Avatar de 2Eurocents
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    2 177
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 2 177
    Points : 3 166
    Points
    3 166
    Par défaut
    En fait, le comportement du || est ici un peu plus complexe car les opérateurs <=> et cmp ne sont pas binaires (0/1) mais ternaires (-1/0/1).

    Du coup, je n'ai pas encore construit ni intégré à ma modeste capacité de réflexion les tables de vérité de leurs conjonctions (opérateurs || ou &&).

    C'est pour cela que ce fonctionnement est un peu mystérieux, mais le mystère ne saurait résister à l'analyse ... dès que je serai un peu moins fainéant ...

    On doit avoir -1 et 1 pour vrai et 0 pour faux ... et comme on retourne le premier élément vrai ... le tri doit être correct.

    Je vais encore y réfléchir ...
    La FAQ Perl est par ici
    : La fonction "Rechercher", on aurait dû la nommer "Retrouver" - essayez et vous verrez pourquoi !

  8. #8
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Euh... c'est bien ce que j'ai dit :
    Il faut savoir par ailleurs que || ne renvoit pas vrai ou faux, mais la valeur de son premier opérande qui est considéré comme vrai. D'où le comportement observé ici !
    Les valeurs fausses, sont undef, 0, "", "0" et je crois que c'est tout... donc toutes les autres valeurs sont vraies.

    --
    Jedaï

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [langage] prob lecture fichier .txt
    Par martijan dans le forum Langage
    Réponses: 3
    Dernier message: 16/07/2003, 11h08
  2. [langage] delete de fichier
    Par lolive dans le forum Langage
    Réponses: 2
    Dernier message: 24/04/2003, 15h04
  3. [langage] Comparaison de fichiers
    Par Jibees dans le forum Langage
    Réponses: 3
    Dernier message: 23/04/2003, 16h27
  4. [langage] TRI TABLEAU ASSOCIATIF
    Par proner dans le forum Langage
    Réponses: 5
    Dernier message: 04/03/2003, 16h38
  5. Réponses: 2
    Dernier message: 26/02/2003, 15h18

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