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 :

détecter si un élément existe dans un hash perl


Sujet :

Langage Perl

  1. #1
    Membre confirmé
    Inscrit en
    Mars 2010
    Messages
    157
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 157
    Par défaut détecter si un élément existe dans un hash perl
    Bonjour

    On sait que pour voir si un élément existe dans un hash perl on utilise le code suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     if(exists $stops{ "$line" } ) {
     
    						 print   FIC2  "$line $j " ;
    						 print   FIC2  $stops{ "$line" } ;
    						;
    						 print   FIC2 "\n" ;
    else
    {
    }
     
                }
    le problème ici même si l'élément n'est pas présent dans le hahs, le programme va exécuter le if est affiché dans mon cas 16178 qui le nombre d'élement du hash
    comment faire pour n'afficher que les éléments présent

    Merci

  2. #2
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    ce n'est pas possible. Le code du if (les trois print ...) ne peut s'exécuter que s'il existe dans le hash %stops une entrée ayant la clef $line.

    Si ton code s'exécute alors que tu penses qu'il n'y a pas d'entrée pour $line, alors vérifie le contenu du hash et le contenu de la variable $line.

    Par ailleurs, le branch else ne servant à rien, il est inutile de la mettre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    if (exists $stops{ "$line" }) {
        print   FIC2  "$line $j " ;
        print   FIC2  $stops{ "$line" } ;
        print   FIC2 "\n" ;
    }
    et je me demande à quoi sert la variable $j et ce qu'elle contient.

    Le problème est sans doute ailleurs dans le code.

  3. #3
    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
    Je pense aussi qu'il faudrait que tu montres le code autour de cet extrait...

  4. #4
    Membre confirmé
    Inscrit en
    Mars 2010
    Messages
    157
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 157
    Par défaut
    Bonjour

    je vous montre le code complet, il lit deux fichier ligne par ligne et il les compare

    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
    52
    53
    54
    55
    56
    57
    58
    #!/usr/bin/perl
    use strict;
    use warnings;
     
    open( FIC,  $ARGV[0] );
    open( FICC, $ARGV[1] );
     
    print "choose the name of the file\n";
     
    chomp( my $fic2 = <STDIN> );
    open( FIC2, ">$fic2" );
    my $i=0;
    my $j=0;
    my $h=0;
    my @b=();
    my %stops;
    while (<FIC>)    #read each line into $_
    {
        # Remove newline from $_
        chomp;
        $_ =~ s/\s+$//;
        $stops{$_} = $i;    # add the line to
        $i++;
    }
     
    close FIC;
     
    while (<FICC>) {
        my $ligne = $_;
        $ligne =~ s/\s+$//;
        $b[$j] = lc($ligne);
     
        # $b contain the data
     
        $j++;
    }
     
    foreach my $che (@b) {
     
        chomp($che);
     
    	       if( $stops{ $che }  ) {
     
     
    						 print   FIC2  $stops{ $che } ;
    						 print   FIC2  " : " ;
    						 print   FIC2 $che ;
    						 print   FIC2 "\n" ;
     
                }
    			 else{ 
    			 }
     
     
     
     
     
    }
    Ici le else n'est jamais exécuté!
    Les deux fichiers en entrée contennent chacun un mot par ligne, ensuite une ligne composé par des espaces ensuite un mot ainsi de suite

    result

    much

    london

    only

    top

    early
    fichier n°2:
    passenger

    saving

    shareholder

    london

    glass

    early
    peut être ces lignes qui contiennent des esapaces affectent le résultats

  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
    Une différence entre tes deux lectures de fichier : la lecture du fichier qui sert à charger @b converti les chaines de texte en minuscule (fonction lc) alors que celle qui sert à charger %stops ne converti pas les chaines en minuscule. Je ne connais pas l'impact que cela peut avoir.

    Après, je ne comprends pas non plus pourquoi le texte du fichier qui sert à charger @b n'est pas chompé au moment où tu le lis et le met dans @b, mais plus tard au moment de tester $stops{ $che } (mais à priori, le problème de devrait pas venir de là).

    Pour bien faire et comprendre ce qui ne va pas, il faudrait aussi fournir un "jeu de test" (fichiers en entrée) histoire de pouvoir tester (ou debugger).

  6. #6
    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
    Bonsoir,

    Le code mis ci-dessus ne me plait vraiment pas .
    La manière d'ouvrir les fichiers n'est pas bonne, la manière de récupérer les fichiers est pas top. Du peu de jeu de données que je vois, je suppose que chaque fichier contient une liste de mots. Si c'est le cas, l'algorithme peut être amélioré en utilisant un petit module Perl pour comparer deux tableaux.

    Merci de nous montrer un jeu de données afin que l'on te propose un code.

  7. #7
    Membre confirmé
    Inscrit en
    Mars 2010
    Messages
    157
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 157
    Par défaut
    Bonsoir

    Voila j'ai donnée un jeu de donné, autre chose le problème n'est pas dans la déclaration de variable, ni autre, le programme il marche correcte , le seul soucis, c'est qu'il n'éxecute jamais le ELSE , mais à la place s'il ne trouve pas l'élément il va afficher un entier qui correspond au nombre d'élément du HASH

  8. #8
    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
    Citation Envoyé par africanwinners Voir le message
    Bonsoir

    Voila j'ai donnée un jeu de donné, autre chose le problème n'est pas dans la déclaration de variable, ni autre, le programme il marche correcte , le seul soucis, c'est qu'il n'éxecute jamais le ELSE , mais à la place s'il ne trouve pas l'élément il va afficher un entier qui correspond au nombre d'élément du HASH
    Le programme ne fonctionne pas correctement sinon, tu n'aurais pas poster un message sur ce problème de else . Nous sommes juste en train de te donner des conseils pour t'améliorer.

  9. #9
    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
    Voilà !

    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
    #!/usr/bin/perl
    use warnings;
    use strict;
    use Getopt::Long;
    use List::Compare;
     
    # Recupération des arguments
    my ( $fichier1, $fichier2 ) = ();
    GetOptions(
    	'fichier1=s' => \$fichier1,
    	'fichier2=s' => \$fichier2,
    );
     
    open my $fh1, '<', $fichier1 or die "Impossible de lire fichier 1 [$fichier1] : $!\n";
    open my $fh2, '<', $fichier2 or die "Impossible de lire fichier 1 [$fichier1] : $!\n";
     
    # Stockage des fichiers dans deux tableax à comparer par la suite
    my @donnees1 = grep { /^\S+$/ } <$fh1>;
    my @donnees2 = grep { /^\S+$/ } <$fh2>;
    foreach (@donnees1) { chomp $_; }
    foreach (@donnees2) { chomp $_; }
    close $fh1;
    close $fh2;
     
    # Comparaison
    my $lc           = List::Compare->new( \@donnees1, \@donnees2 );
    my @intersection = $lc->get_intersection;
    my @IniqueFic1   = $lc->get_unique;
    my @IniqueFic2   = $lc->get_complement;
     
    print "Unique au fichier 1 : @IniqueFic1\n";
    print "Unique au fichier 2 : @IniqueFic2\n";
    print "Present dans les deux fichiers 1 : @intersection\n";
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >perl test.pl -fichier1 fic1.txt -fichier2 fic2.txt
    Unique au fichier 1 : early much only result top
    Unique au fichier 2 : glass passenger saving shareholder
    Present dans les deux fichiers 1 : london

  10. #10
    Membre confirmé
    Inscrit en
    Mars 2010
    Messages
    157
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 157
    Par défaut
    Merci bien pour cette réponse.
    Mais ma solution est plus efficace, puisqu'elle élimine les espaces si les lignes contiennent des espaces, de plus je peux récupérer des informations importante pour mon programme qui sont le $j (indice du numéro d'élément dans le fichier) et les indices du hash.
    C'est pour ca j'ai utilisé cette méthode
    Merci bien

  11. #11
    Membre confirmé
    Inscrit en
    Mars 2010
    Messages
    157
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 157
    Par défaut
    Citation Envoyé par djibril Voir le message
    Bonsoir,

    Le code mis ci-dessus ne me plait vraiment pas .
    La manière d'ouvrir les fichiers n'est pas bonne, la manière de récupérer les fichiers est pas top. Du peu de jeu de données que je vois, je suppose que chaque fichier contient une liste de mots. Si c'est le cas, l'algorithme peut être amélioré en utilisant un petit module Perl pour comparer deux tableaux.

    Merci de nous montrer un jeu de données afin que l'on te propose un code.
    Je comprends pas pourquoi la méthodes d'ouverture des fichiers n'est pas bonne? juste pour ma formation

  12. #12
    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
    Citation Envoyé par africanwinners Voir le message
    Mais ma solution est plus efficace, puisqu'elle élimine les espaces si les lignes contiennent des espaces, de plus je peux récupérer des informations importante pour mon programme qui sont le $j (indice du numéro d'élément dans le fichier) et les indices du hash.
    C'est pour ca j'ai utilisé cette méthode
    Merci bien
    Bon, tu fais comme tu veux. Par exemple, on essaye juste de te proposer une solution plus optimum et te montrer qu'il bon d'utiliser de bonnes pratiques. Maintenant, tu en fais ce que tu veux. Ne connaissant pas ton cahier des charges, on ne peut pas te solutionner à 100% ton problème. Néanmoins, le code que l'on te propose peut être compléter pour palier à des manques.
    Dire que le programme est plus efficace juste parce qu'il élimine les espaces est un peu... en une ligne de code, la gestion des espaces peut se faire également.
    Enfin, il y a des modules CPAN beaucoup mieux écrit et bien plus rapide que ce que l'on écrit habituellement, dommage de s'en priver.

    Pour revenir à l'ouverture des fichiers, il faut utiliser la fonction open avec trois arguments et pas deux.

  13. #13
    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
    Moi, quand j'exécute le script que tu as fourni dans ton message 4, avec les deux fichiers d'exemple (contenant les lignes avec des espaces), j'obtiens le résultat suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    9 :
    9 :
    9 :
    4 : london
    9 :
    9 :
    10 : early
    Et london et early sont les deux mots en commun dans les deux fichiers.
    Le problème, à mon avis, vient du fait que tu enregistres comme des données (dans @b et %stops) le contenu des lignes vides (c'est à dire, une ligne vide puisque tu supprimes les espaces). Du coup, tu as des matches qui s'opère et affichent des concordances sans "mot" (lignes 1 à 3, lignes 5 à 6 dans le fichier résultat).

    En éliminant ces lignes "vides" dans le script au moment de la lecture des fichiers, j'obtiens le résultat suivant :
    Après, ton écriture n'est pas très perlish, c'est vrai, mais c'est n'est pas non plus le plus important à ce stade.

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

Discussions similaires

  1. détecter si une valeur existe dans un array
    Par cedrick21 dans le forum Général JavaScript
    Réponses: 7
    Dernier message: 15/12/2010, 11h09
  2. Message si l'élément existe dans la table
    Par aymane19 dans le forum VB 6 et antérieur
    Réponses: 1
    Dernier message: 11/05/2008, 19h13
  3. Savoir si un élément existe dans un tableau
    Par peuf23 dans le forum Langage
    Réponses: 2
    Dernier message: 30/06/2006, 12h09

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