2010-07-20 4 views
1

Résumé du résumé:Comment utiliser Perl pour analyser le texte formaté spécifié avec regex?

comment analyser le fichier texte en deux "hachages" en Perl. Des paires clé-valeur d'un magasin tirées de la partie (X = Y), une autre de la partie (X: Y)?

1=9 
2=2 
3=1 
4=6 
2:1 
3:1 
4:1 
1:2 
1:3 
1:4 
3:4 
3:2 

ils sont conservés dans un fichier, et seul le symbole entre les deux chiffres indique la différence.

============================================== ====================================

Je viens de passer environ 30 heures à apprendre Perl au cours du dernier semestre et géré finir mon devoir de Perl de façon «tête première, ad hoc, moche». Je viens de recevoir mon résultat pour cette section en tant que 7/10, pour être franc, je ne suis pas content, surtout parce qu'il me rappelle mon mauvais souvenir d'essayer d'utiliser Regular Expression pour traiter des données formatées, ce qui est comme ceci:

1= (the last digit in your student ID,or one if this digit is zero) 
2= (the second last digit in your student ID,or one if this digit is zero) 
3= (the third last digit in your student ID, or one if this digit is zero) 
4= (the forth last digit in your student ID, or one if this digit is zero) 

2:1 
3:1 
4:1 
1:2 
1:3 
1:4 
2:3 (if the last digit in your student ID is between 0 and 4) OR 
    3:4 (if the last digit in your student ID is between 5 and 9) 
3:2 (if the second last digit in your student ID is between 0 and 4) OR 
    4:3 (if the second last digit in your student ID is between 5 and 9) 

An example of the above configuration file: if your student ID is 10926029, it has to be: 

1=9 
2=2 
3=1 
4=6 
2:1 
3:1 
4:1 
1:2 
1:3 
1:4 
3:4 
3:2 

l'affectation était sur le calcul Pagerank, l'algorithme est simplifié si je suis venu avec la réponse à cette partie en 5 minutes. Cependant, c'était la partie analyse de texte qui m'a pris beaucoup de temps.

La première partie du texte (Page = Pagerank) indique les pages et les pageranks correspondants.

La deuxième partie (FromNode: ToNode) indique la direction d'un lien entre deux pages.

Pour une meilleure compréhension, s'il vous plaît aller sur mon site et vérifier le fichier des besoins et mon script Perl here

Il y a des commentaires massives dans le script, donc je pense qu'il est pas difficile du tout de voir comment j'étais stupide dans ma solution :(

Si vous êtes toujours sur cette page, laissez-moi expliquer pourquoi je pose cette question ici SO:

Je n'ai rien d'autre que « Résultat 7/10 » sans commentaire de l'uni 0 Je ne suis pas étudiant pour uni, j'apprends pour moi-même. Donc, j'espère que les gourous Perl peuvent au moins me guider dans la bonne direction pour résoudre ce problème. Ma solution stupide était en quelque sorte "générique" et probable fonctionnerait en Java, C#, etc. Je suis sûr que ce n'est même pas proche de la nature de Perl.

Et, si possible, s'il vous plaît laissez-moi savoir le niveau de solution, comme je l'ai besoin de passer par "Learning Perl ==> Programmation Perl ==> Master Perl" pour y arriver :)

Merci pour tout indice et suggestion à l'avance.

Edit 1:

J'ai une autre question, mais posté fermé here, qui décrit à peu près comme la façon dont les choses vont dans mon uni :(

+2

J'ai une suggestion sérieuse: allez voir votre professeur et dites-lui que vous aimeriez revoir un peu le problème. Dites clairement que vous ne cherchez pas à changer votre note, mais seulement pour mieux comprendre le matériel. La plupart des enseignants auront du mal à refuser cela. – Telemachus

+0

@Telemachus: après des années d'études dans cette université, je suis sûr que ce genre de chose ne se produirait que si je poursuivais le prof. pour un retour en personne. Je sais que ça a été marqué par quelqu'un d'autre. Ils pourraient reconnaître cela comme "problème dans le passé". Je suis tellement malade de cela. Et pour être franc, je ne pense pas qu'ils me montreraient une meilleure solution :( –

+3

Votre question est impénétrable Que demandez-vous? Je ne veux pas passer 45 minutes juste pour comprendre ce que vous demandez. Si vous voulez une réponse, écrivez une question courte et claire et donnez un petit peu de code – daotoad

Répondre

3

Est-ce que vous voulez dire?L'expression rationnelle a essentiellement trois groupes de capture (désignés par les () s). Il doit capturer un chiffre, suivi par = ou : (c'est le groupe de capture enveloppant la classe de caractères [], qui correspond à tout caractère à l'intérieur), suivi d'un autre chiffre.

my (%assign, %colon); 

while (<DATA>) { 
    chomp;      
    my ($l, $c, $r) = $_ =~ m/(\d)([=:])(\d)/; 

    if (q{=} eq $c) { $assign{$l} = $r; } 
    elsif (q{:} eq $c) { $colon{$l} = $r; } 
}   

__DATA__ 
1=9 
2=2 
3=1 
4=6 
2:1 
3:1 
4:1 
1:2 
1:3 
1:4 
3:4 
3:2 

Quant à la recommandation, récupérer une copie de Mastering Regular Expressions si vous le pouvez. C'est très ... complet.

+0

C'est absolument mieux que ce que j'ai fait. J'essayais de faire l'analyse syntaxique et la validation des données dans le même processus et je me suis retrouvé avec un script désordonné. En outre, Rings pour le livre recommandé. –

+0

Je recommanderai aussi le livre, je l'ai utilisé au travail et cela m'a beaucoup aidé, je recommande toujours d'apprendre la regex, c'est très utile dans l'analyse des données, j'ajouterais une réponse mais ça semble couvert. – onaclov2000

+0

Votre code supprime les liens de 1 à 2 et 3, en conservant uniquement le lien de 1 à 4. Un hachage simple ne peut pas associer plusieurs valeurs à une seule touche. – daotoad

1

Eh bien, si vous ne voulez pas valider les restrictions sur le fichier de données, vous pouvez facilement analyser ces données. Le problème principal réside dans la sélection de la structure appropriée pour stocker vos données.

use strict; 
use warnings; 

use IO::File; 

my $file_path = shift; # Take file from command line 

my %page_rank; 
my %links; 

my $fh = IO::File->new($file_path, '<') 
    or die "Error opening $file_path - $!\n"; 

while (my $line = $fh->readline) { 
    chomp $line; 

    next unless $line =~ /^(\d+)([=:])(\d+)$/; # skip invalid lines 

    my $page  = $1; 
    my $delimiter = $2; 
    my $value  = $3; 


    if($delimiter eq '=') { 

     $page_rank{$page} = $value; 
    } 
    elsif($delimiter eq ':') { 

     $links{$page} = [] unless exists $links{$page}; 

     push @{ $links{$page} }, $value; 
    } 

} 

use Data::Dumper; 
print Dumper \%page_rank; 
print Dumper \%links; 

La principale façon que ce code diffère de celui de Pedro Silva est que le mien est plus bavard et il gère également plusieurs liens d'une page correctement. Par exemple, mon code préserve toutes les valeurs des liens de la page 1. Le code de Pedro rejette tout sauf le dernier.

+0

@daotoad: J'aime l'utilisation de modules. C'était douloureux de ne pas pouvoir utiliser aucun d'entre eux dans mon code original ... –

+0

IO :: File est un module de base et je l'ai utilisé pour améliorer la lisibilité sur l'opérateur '<>'.Il n'y a pas de fonctionnalité supplémentaire qui n'aurait pas pu être obtenue avec une syntaxe 'open' et' <> ', juste un peu plus propre (IMO). – daotoad

Questions connexes