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 :

Perl : Tri de données.


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2010
    Messages : 8
    Par défaut Perl : Tri de données.
    Bonjour,

    Ce qui suit a trait au tri dans des données.

    Ce texte a été mal déposé dans la rubrique "discussion".
    Je vais tenter de le virer de là...

    Voilà 9 jours que j'ai débuté l'étude de Perl pour pouvoir manipuler un gros fichier qui va encore croître.
    J'ai fais pas mal de choses mais maintenant je cale.
    Et je sais que c'est l'emploi des hashes qui me pose problème.
    Pourriez vous me dire comment aborder mon problème, assez banal, je crois.

    Après je pourrai avancer tout seul un peu plus loin...

    Mon fichier se nomme trier.txt
    Il a la srtucture suivante:

    FLAG_CONSTANT
    WALL LARRY
    Datas en texte libre de longueurs différentes
    Nombre de lignes variable
    Data_WALL Data_WALL Data_WALL

    Data_WALL

    Data_WALL Data_WALL


    FLAG_CONSTANT
    CESAR JULES
    Datas en texte libre de longueurs différentes
    Nombre de lignes variable
    Data_CESAR
    Data_CESAR Data_CESAR

    FLAG_CONSTANT
    OBAMA BARAK
    Datas en texte libre de longueurs différentes
    Nombre de lignes variable
    Data_OBAMA Data_OBAMA
    Data_OBAMA

    Data_OBAMA

    ######

    Je voudrais, faire un tri, par ordre alphabétique, sur la deuxième ligne
    de ces "fiches" et obtenir en sortie:

    FLAG_CONSTANT
    CESAR JULES
    Datas en texte libre de longueurs différentes
    Nombre de lignes variable
    Data_CESAR
    Data_CESAR Data_CESAR

    FLAG_CONSTANT
    OBAMA BARAK
    Datas en texte libre de longueurs différentes
    Nombre de lignes variable
    Data_OBAMA Data_OBAMA
    Data_OBAMA

    Data_OBAMA

    FLAG_CONSTANT
    WALL LARRY
    Datas en texte libre de longueurs différentes
    Nombre de lignes variable
    Data_WALL Data_WALL Data_WALL

    Data_WALL

    Data_WALL Data_WALL
    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
    ####################
    # Avec le script suivant j'affiche les noms seuls, mais 
    # ils ne sont pas triés. 
    #Les Datas attachées à chaque nom ne suivent évidemment pas.
     
    use strict;
    use warnings;
    use diagnostics;
     
    open FICHIER,"< trier.txt" or die "Le fichier n'existe pas !";
     
    my $i = 0;
     
    while (<FICHIER>) {
     
    /FLAG_CONSTANT/and $i = 0;
     
    print " $_" if $i==1;
     
    ++$i; 
     
    }
     
    close FICHIER;
    ####################"

    Merci d'avance.

    Roland.

  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
    Je voudrais, faire un tri, par ordre alphabétique, sur la deuxième ligne
    Utilisons comme clé de hash le nom et le prénom.

    Il y a plusieurs possibilités, en voici une :
    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
     
    #!/bin/perl -w
     
     
    ####################
    # Avec le script suivant j'affiche les noms seuls, mais 
    # ils ne sont pas triés. 
    #Les Datas attachées à chaque nom ne suivent évidemment pas.
     
    use strict;
    use warnings;
    use diagnostics;
     
    open FICHIER,"< data.txt" or die "Le fichier n'existe pas !";
     
     
    my %data;
    my $name;
     
     
    while (my $line = <FICHIER>) {
     
     
    	# on vide la clé pour le bloc suivant (sécurité - pas nécessaire)
    	if ($line =~ m/FLAG_CONSTANT/){
    		$name = '';
    	}  
    	# nouvelle clé (nom-prénom)
    	elsif ($line =~ m/^([A-Z]+\s[A-Z]+)$/){
    		$name = $1;
    	} 
    	# données associées
    	elsif (defined $name) {
    		push @{$data{$name}}, $line;
    	}	
    }
     
    close FICHIER;
     
    # tri
    foreach my $name (sort keys %data){
     
    	print 'FLAG_CONSTANT'."\n";
    	print $name."\n";
    	map {print $_} @{$data{$name}};
     
    }

    Il faut être certain que
    - tu as toujours le nom en majuscules séparé d'un seul espace suivi du prénom en majuscules
    - aucune des lignes centrales ne peut avoir cette structure

  3. #3
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Bonjour,



    Le problème m’a intéressé. Je l’ai traité avec les expressions rationnelles, en Python.
    Pourquoi ne vous êtes vous pas dirigé immédiatement sur le recours aux regex ?



    J’ai appelé EOL les fins de lignes: soit ’\r’ soit ’\r\n’ soit ’\n’ selon le système d’exploitation. La valeur de EOL est déterminée par le programme. Ainsi les codes sont portables.

    J’ai fait l’hypothèse que les seules lignes “FLAG_CONSTANT“ sont les premières lignes des blocs et qu’il n’y a pas d’autres lignes “FLAG_CONSTANT“+EOL
    S’il existe le mot FLAG_CONSTANT dans une ligne mais non suivi de EOL, mes codes marcheront quand même.

    j’ai ajouté une séparation des blocs par une ligne de pointillés.





    Le premier programme enregistre dans une liste les blocs amputés de la premiére ligne.
    Le début de chaque élément de la liste obtenu est donc la deuxième ligne d’un bloc. On peut donc faire trier la liste sur la base de la deuxième ligne par une simple instruction la.sort()
    On joint ensuite tous les éléments de la liste pour une écriture dans le fichier réceptionnaire.

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import re
    pat = re.compile('FLAG_CONSTANT(\r?\n)(.+?(?=FLAG_CONSTANT|\Z))',re.DOTALL)
     
    with open('flagy.txt','rb') as f:
        la = [ ma.group(2).rstrip() for ma in pat.finditer(f.read())]
    EOL = ma.group(1)
    la.sort()
     
    glu = EOL+EOL+'------------------------'+EOL+'FLAG_CONSTANT'+EOL
    with open('flagy new.txt','wb') as g:
        g.write('FLAG_CONSTANT'+EOL)
        g.write(glu.join(u for u in la))


    Avec le fichier primaire suivant:
    Code python : 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
    FLAG_CONSTANT
    JASON RYZNAR
     
    Data_RYZNAR
     
    né le 19 février 1983 à Anchorage, Alaska, aux États-Unis 
    est un joueur de hockey sur glace américain.
     
    Data_RYZNAR
     
     
     
    FLAG_CONSTANT
    WALL LARRY 
    Datas en texte libre de longueurs différentes
    Nombre de lignes variable
    Data_WALL Data_WALL Data_WALL
     
    Data_WALL 
     
    Data_WALL Data_WALL
     
     
    FLAG_CONSTANT
    CESAR JULES 
    Datas en texte libre de longueurs différentes
    Nombre de lignes variable
    Data_CESAR
    Data_CESAR Data_CESAR
     
    FLAG_CONSTANT
    OBAMA BARAK 
    Datas en texte libre de longueurs différentes
    Nombre de lignes variable
    Data_OBAMA Data_OBAMA
    Data_OBAMA
     
    Data_OBAMA
     
     
     
     
     
    FLAG_CONSTANT
    JULIUS RUPP
     
    (né le 13 août 1809 à Königsberg - 
    mort le 11 juillet 1884 à Königsberg) 
    était un théologien, professeur et militant pacifiste allemand.

    le résultat est ceci:
    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
    FLAG_CONSTANT
    CESAR JULES 
    Datas en texte libre de longueurs différentes
    Nombre de lignes variable
    Data_CESAR
    Data_CESAR Data_CESAR
     
    ------------------------
    FLAG_CONSTANT
    JASON RYZNAR
     
    Data_RYZNAR
     
    né le 19 février 1983 à Anchorage, Alaska, aux États-Unis 
    est un joueur de hockey sur glace américain.
     
    Data_RYZNAR
     
    ------------------------
    FLAG_CONSTANT
    JULIUS RUPP
     
    (le 13 août 1809 à Königsberg - 
    mort le 11 juillet 1884 à Königsberg) 
    était un théologien, professeur et militant pacifiste allemand.
     
    ------------------------
    FLAG_CONSTANT
    OBAMA BARAK 
    Datas en texte libre de longueurs différentes
    Nombre de lignes variable
    Data_OBAMA Data_OBAMA
    Data_OBAMA
     
    Data_OBAMA
     
    ------------------------
    FLAG_CONSTANT
    WALL LARRY 
    Datas en texte libre de longueurs différentes
    Nombre de lignes variable
    Data_WALL Data_WALL Data_WALL
     
    Data_WALL 
     
    Data_WALL Data_WALL





    Le second programme produit un résultat strictement identique mais ne procède pas de la même façon.

    Il dresse une liste dont chaque élément est un tuple comportant d’abord la seconde ligne d’un bloc, puis la position de début et la position de fin du bloc complet dans le fichier de départ.

    On transfert ensuite chaque bloc l’un après l’autre en déplaçant le pointeur de fichier dans le premier fichier pour le positionner au début de chaque bloc à transférer , avant de lire le nombre précis d’octets que comporte le bloc.

    On évite ainsi de créer une liste des blocs (ce que faisait le premier programme , hormise le premire ligne de chaque bloc) , qui sera énorme quand le fichier sera très gros. En procédant ainsi , on évite de surcharger d’un coup la RAM.

    Par contre c’est le disque dur qui encaisse : arrivé à la fin du transfert, avant d’effacer le premier fichier, pendant un court instant, il y deux fichiers de tailles sensiblement égales.

    On peut imaginer des algorithmes plus complexes si le DD a de la peine à assurer l’enregistrement d’autant de données, par exemple effacer dans le premier fichier chaque bloc qui vient d’être transféré, ou faire des transferts en regroupant plusieurs blocs traités d’un coup, etc.


    La fonction rstrip() élimine les blancs à la fin de chaque bloc.

    Code python : 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
    import re
    pit = re.compile('FLAG_CONSTANT(\r?\n)([^\r\n]+)\r?\n.+?(?=FLAG_CONSTANT|\Z)',re.DOTALL)
     
    f = open('flagy.txt','rb')
    li = [ (ma.group(2),ma.start(),ma.end()) for ma in pit.finditer(f.read()) ]
    EOL = ma.group(1)
    li.sort()
     
    intercal = EOL+EOL+'------------------------'+EOL
    with open('flagy new2.txt','wb') as g:
        (x,deb,fin) = li[0]
        f.seek(deb)
        g.write(f.read(fin-deb).rstrip())
        for (x,deb,fin) in li[1:]:
            f.seek(deb)
            g.write(intercal + f.read(fin-deb).rstrip())
    f.close()

  4. #4
    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
    Attention, nous ne sommes pas ici dans un forum python.

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Bonjour djibril,



    Comme je ne connais que Python mais que j’adore les problèmes de regex, j’apporte parfois mes propositions dans d’autres forums que le forum Python sur le sujet des regex, en ne postant toutefois habituellement que les RE , sauf si l’algorithme a en lui même une importance. Ce qui est le cas pour ce problème.
    Python étant facilement compréhensible, je pense que ça ne pose pas un gros problème à des non pratiquants de Python de comprendre un algorithme simple écrit en Python.

    Les quelques fois où j’ai posté un code Python en dehors de son forum, on ne m’a pas alerté sur les balises à mettre comme tu les as corrigées. Une prochaine fois, j’y penserai.

  6. #6
    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
    En fait, pour ma part, je n'arrive pas à voir en quoi ce problème est traitable par des expressions rationnelles... C'est un problème de tri et d'organisation de donnée, rien de plus, non ?
    Le fait d'utiliser une expression rationnelle, notamment pour détecter le début de bloc, n'en fait pas à mes yeux une problématique "d'expression rationnelle". De plus, Yeswecan a dès le début introduit une regexp dans son code perl.
    Mais peut-être ai-je mal compris ?

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

Discussions similaires

  1. Tri de données dans un tableau
    Par GESCOM2000 dans le forum Contribuez
    Réponses: 6
    Dernier message: 06/12/2006, 15h55
  2. tri des données différent entre 2 bases
    Par j6m dans le forum Oracle
    Réponses: 2
    Dernier message: 12/03/2006, 10h17
  3. gestion et tri de donnée en mémoire
    Par lenectar dans le forum C++
    Réponses: 2
    Dernier message: 05/10/2005, 13h18
  4. [JTable] Tri des données
    Par soulhouf dans le forum Composants
    Réponses: 7
    Dernier message: 08/09/2005, 14h01
  5. [CR9] Tri de données
    Par Madduck dans le forum SAP Crystal Reports
    Réponses: 3
    Dernier message: 24/07/2003, 09h30

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