Comment puis-je correspondre à l'ordre de chaîne entre deux documents en Perl?

StackOverflow https://stackoverflow.com/questions/2894213

  •  04-10-2019
  •  | 
  •  

Question

J'ai un problème à faire un programme PERL pour faire correspondre les mots dans deux documents. Disons qu'il ya des documents A et B.

Je veux supprimer les mots dans le document A qui est pas dans le document B.

Exemple 1 :

A: Je mange une pizza

B: Elle va au marché et manger de la pizza

Résultat: manger de la pizza

Exemple 2 : A: manger de la pizza

B: Pizza manger

Résultat: Pizza (L'ordre des mots est pertinent, donc « manger » est supprimé.)

J'utilise Perl pour le système et les phrases de chaque document est pas dans un grand nombre, donc je pense que je ne vais pas utiliser SQL

Et le programme est un subproram pour le classement de l'essai automatique pour la langue indonésienne (bahasa)

Thanx, Désolé si ma question est un peu déroutant. Je suis vraiment nouveau à « ce monde »:)

Était-ce utile?

La solution

OK, je suis sans accès au moment donc ce n'est pas garanti à 100% ou même compiler mais devrait fournir suffisamment d'indications:

Solution 1 : (ordre des mots n'a pas d'importance)

#!/usr/bin/perl -w

use strict;
use File::Slurp;

my @B_lines = File::Slurp::read_file("B") || die "Error reading B: $!";
my %B_words = ();
foreach my $line (@B_lines) {
    map { $B_words{$_} = 1 } split(/\s+/, $line);
}
my @A_lines = File::Slurp::read_file("A") || die "Error reading A: $!";
my @new_lines = ();
foreach my $line (@A_lines) {
    my @B_words_only = grep { $B_words{$_} } split(/\s+/, $line);
    push @new_lines, join(" ", @B_words_only) . "\n";
}
File::Slurp::write_file("A_new", @new_lines) || die "Error writing A_new: $!";

Cela devrait créer un nouveau fichier « A_new » qui ne contient que les mots de A qui sont en B.

a un léger bug - il remplacera tout plusieurs espaces dans le fichier A avec un seul espace, donc

    word1        word2              word3

deviendra

word1 word2 word3

Il peut être fixé, mais serait vraiment gênant de le faire, donc je ne l'ai pas pris la peine à moins que vous absolument exiger que 100% correctement les espaces soient conservées

Solution 2 : (mot d'ordre des questions, mais vous pouvez imprimer des mots à partir du fichier A avec pas ce qui a trait à la préservation des espaces du tout)

#!/usr/bin/perl -w

use strict;
use File::Slurp;

my @A_words = split(/\s+/gs, File::Slurp::read_file("A") || die "Error reading A:$!");
my @B_words = split(/\s+/gs, File::Slurp::read_file("B") || die "Error reading B:$!");
my $B_counter = 0;
for (my $A_counter = 0; $A_counter < scalar(@A_words); ++$A_counter) {
    while ($B_counter < scalar(@B_words)
        && $B_words[$B_counter] ne $A_words[$A_counter]) {++$B_counter;}
    last if $B_counter == scalar(@B_words);
    print "$A_words[$A_counter]";
}

Solution 3 (pourquoi avons-nous besoin de Perl à nouveau? :))

Vous pouvez le faire trivialement en shell sans Perl (ou un appel ou backticks dans un script Perl parent via le système ())

comm -12 A B | tr "\012" " " 

Pour appeler cela de Perl:

my $new_text = `comm -12 A B | tr "\012" " " `;

Mais voir mon dernier commentaire pourquoi cela peut être considéré comme « mauvais Perl » ... au moins si vous faites cela dans une boucle avec de très nombreux fichiers itéré et de soins sur la performance.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top