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 :

lecture d'un fichier ligne par ligne


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2017
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 33
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2017
    Messages : 29
    Par défaut lecture d'un fichier ligne par ligne
    Bonjour à tous,

    J'ai deux fichier que je veux les lire lignes par ligne, ( le premier contenant un mot par ligne et le deuxième une phrase par ligne) , donc je veux pour chaque mot du premier fichier calculer le nombre des phrases de deuxième fichier contenant ce mot,
    voilà mon code :
    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
     
    #calcul le IDF d'un mot
     
        use strict;
        use warnings;
        use autodie;
        use utf8;
     
     
    my $nbre_ligne = 4159480;
     
    open(my $CorpusMots, '<:utf8', '/home/lenovo/Bureau/MesTravaux/IDF/test') or die "Unable to open for read: $!";
    open(my $CorpusPhrases, '<:utf8', '/home/lenovo/Bureau/MesTravaux/IDF/phrases') or die "Unable to open for read: $!";
    open my $fh_resultat, ">:utf8", '/home/lenovo/Bureau/MesTravaux/IDF/result';
     
     
     
     
     
    my $word;
    while(defined(  $word =  <$CorpusMots> )) {
    chomp $word ;
    $word =~ s/^\s*|\s*$//g;
    my $nb_phrase = 0;
    my $idf;
    my $ph;
    while (defined ( $ph = <$CorpusPhrases> ))
    {
    my @tab = split(/ /, $ph);
    chomp @tab ;
    foreach my $val(@tab) {
     if($word eq $val) 
    {
    $nb_phrase = $nb_phrase + 1;
    last;
    }
    }
    }
    #calcul log 
    if ($nb_phrase == 0) 
    {
    $idf =0;
    }
    else
    {
    $idf = (log(3/$nb_phrase))/log(10);
    }
     
    print $fh_resultat "$word:$idf\n";
    }
    Le code semble bien mais le résultat est faux, en fait l'exécution se fait seulement pour le premier mot du fichier , pourquoi ??

  2. #2
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2017
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2017
    Messages : 25
    Par défaut
    Je trouve assez pénible de lire un code non-indenté, ça passe sur celui-ci qui est plutôt simple et court, mais pour du code un peu plus compliqué, essaie d'indenter stp.
    Ceci-dit, j'ai l'impression que tu te compliques énormément.
    Dans ta 2nde boucle (celle qui est à l'intérieur de la première) essaie plutôt d'utiliser une expression régulière toute bête qui comptera le nombre d'occurences, et à chaque résultat qu'elle trouve, augmente ton compteur du nombre d'occurrences trouvées.
    En tentant de gérer les occurrences multiples sur une ligne, tu te fais des nœuds au cerveau pour quelque chose qui ne m'a pas l'air si difficile (je peux me tromper).

  3. #3
    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,

    Merci d'apprendre à indenter proprement vos codes pour une meilleure lisibilité :

    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
    #!/usr/bin/perl 
     
    #calcul le IDF d'un mot
     
    use strict;
    use warnings;
    use autodie;
    use utf8;
     
    my $nbre_ligne = 4159480;
     
    open( my $CorpusMots,    '<:utf8', '/home/lenovo/Bureau/MesTravaux/IDF/test' )    or die "Unable to open for read: $!";
    open( my $CorpusPhrases, '<:utf8', '/home/lenovo/Bureau/MesTravaux/IDF/phrases' ) or die "Unable to open for read: $!";
    open my $fh_resultat, ">:utf8", '/home/lenovo/Bureau/MesTravaux/IDF/result';
     
    my $word;
    while ( defined( $word = <$CorpusMots> ) ) {
    	chomp $word;
    	$word =~ s/^\s*|\s*$//g;
    	my $nb_phrase = 0;
    	my $idf;
    	my $ph;
    	while ( defined( $ph = <$CorpusPhrases> ) ) {
    		my @tab = split( / /, $ph );
    		chomp @tab;
    		foreach my $val (@tab) {
    			if ( $word eq $val ) {
    				$nb_phrase = $nb_phrase + 1;
    				last;
    			}
    		}
    	}
     
    	#calcul log
    	if ( $nb_phrase == 0 ) {
    		$idf = 0;
    	}
    	else {
    		$idf = ( log( 3 / $nb_phrase ) ) / log(10);
    	}
     
    	print $fh_resultat "$word:$idf\n";
    }

  4. #4
    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
    Citation Envoyé par djibril Voir le message
    Bonsoir,

    Merci d'apprendre à indenter proprement vos codes pour une meilleure lisibilité :
    ++.

  5. #5
    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 Ftina,

    il est très inefficace de lire ton deuxième fichier (phrases) autant de fois qu'il y a de mots dans le premier fichier. Sauf si tes fichiers sont énormes, il faut charger l'un d'eux en mémoire (tableau ou hachage), puis lire l'autre une seule fois en le comparant à chacun des éléments que tu as stocké en mémoire.

    Si tu veux pour chaque mot le nombre de phrases où il apparaît (si j'ai bien compris), le plus simple est sans doute de mettre tes mots dans un hachage qui te servira de compteur.

    Un truc dans ce genre (pas testé car il n'y a pas d'exemple de données):
    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
     
    open ... # x3 -> ouverture des trois fichiers
     
    my %words;   # hachage de compteurs
     
    while (my $word = <$CorpusMots> ) {
        chomp $word;
        $words{$word} = 0;
    }
    close $CorpusMots;
     
    while (my $phrase = <$CorpusPhrases>) {
        for my $word (keys %words) {
            $words{$word}++ if index ($phrase, $word) >= 0;  # fonction index bien plus rapide qu'une comparaison individuelle à chaque mot de la phrase (ou même qu'une regex)
        }
    }
    close $CorpusPhrases;
     
    # relire le hash de compteurs et imprimer le résultat dans le fichier de sortie
    for my $word (keys %words) {
        print $fh_resultat "Le mot $word apparaît dans %words{$word} phrases.\n"; # (phrase d'exemple  à remplacer par ton calcul de logarithme)
    }

  6. #6
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2017
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 33
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2017
    Messages : 29
    Par défaut
    Citation Envoyé par Lolo78 Voir le message
    Bonjour Ftina,

    il est très inefficace de lire ton deuxième fichier (phrases) autant de fois qu'il y a de mots dans le premier fichier. Sauf si tes fichiers sont énormes, il faut charger l'un d'eux en mémoire (tableau ou hachage), puis lire l'autre une seule fois en le comparant à chacun des éléments que tu as stocké en mémoire.

    Si tu veux pour chaque mot le nombre de phrases où il apparaît (si j'ai bien compris), le plus simple est sans doute de mettre tes mots dans un hachage qui te servira de compteur.

    Un truc dans ce genre (pas testé car il n'y a pas d'exemple de données):
    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
     
    open ... # x3 -> ouverture des trois fichiers
     
    my %words;   # hachage de compteurs
     
    while (my $word = <$CorpusMots> ) {
        chomp $word;
        $words{$word} = 0;
    }
    close $CorpusMots;
     
    while (my $phrase = <$CorpusPhrases>) {
        for my $word (keys %words) {
            $words{$word}++ if index ($phrase, $word) >= 0;  # fonction index bien plus rapide qu'une comparaison individuelle à chaque mot de la phrase (ou même qu'une regex)
        }
    }
    close $CorpusPhrases;
     
    # relire le hash de compteurs et imprimer le résultat dans le fichier de sortie
    for my $word (keys %words) {
        print $fh_resultat "Le mot $word apparaît dans %words{$word} phrases.\n"; # (phrase d'exemple  à remplacer par ton calcul de logarithme)
    }
    Bonsoir LOLO et merci beaucoup pour votre réponse,

    vous voulez dire quoi par : Sauf si tes fichiers sont énormes, il faut charger l'un d'eux en mémoire (tableau ou hachage), puis lire l'autre une seule fois en le comparant à chacun des éléments que tu as stocké en mémoire. (est ce que cettesolution est efficace pour les fichiers de grande taille ? )
    Merci beaucoup de me répondre

Discussions similaires

  1. Réponses: 9
    Dernier message: 03/07/2014, 18h08
  2. lire fichier .txt (NOTEPAD) ligne par ligne
    Par skambram dans le forum VB.NET
    Réponses: 1
    Dernier message: 06/06/2009, 18h41
  3. lire un fichier de string ligne par ligne
    Par bilzzbenzbilz dans le forum Entrée/Sortie
    Réponses: 4
    Dernier message: 11/02/2009, 10h44
  4. [lecture d'un fichier] ligne par ligne
    Par pitit777 dans le forum C++
    Réponses: 3
    Dernier message: 26/11/2005, 11h22
  5. [debutant]lecture fichier ligne par ligne
    Par Battosaiii dans le forum C
    Réponses: 2
    Dernier message: 13/11/2005, 19h02

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