2009-07-09 9 views
5

Ho un incarico di programmazione in Perl che mi richiede di effettuare le seguenti operazioni:Come posso costruire un albero genealogico con Perl?

  1. crea una tabella in un database MySQL, e inserisce questi record in esso:

  2. Carica i dati dalla tabella in una serie di istanze di classe Son.

  3. Utilizzando la matrice, crea il codice HTML che rappresenta un albero padre-figlio e stampa il codice html su STDOUT. Non è necessario rendere l'albero un bell'aspetto. Qualcosa di simile a questo sarebbe bene:

tree http://i25.tinypic.com/314t177.png

sto a corto di idee, si prega di aiuto. mio codice è il seguente:

#!/usr/bin/perl 

use strict; 
use Son; 
use CGI; 
use Data::Dumper; 
use DBI; 
my $q = new CGI; 

#DB connect vars 
my $user = "##"; 
my $pass = "##"; 
my $db = "##"; 
my $host = "localhost"; 

my $dsn = "DBI:mysql:database=$db;host=$host"; 

my $dbh = DBI->connect($dsn,$user,$pass); 
eval { $dbh->do("DROP TABLE sons") }; 
print "Drop failed: [email protected]\n" if [email protected]; 

$dbh->do("CREATE TABLE sons (son VARCHAR(30) PRIMARY KEY, father VARCHAR(30))"); 

my @rows = (["bill", "sam"], 
     ["bob", ""], 
     ["jack", "sam"], 
     ["jone", "mike"], 
     ["mike", "bob"], 
     ["sam", "bob"] 
); 

for my $i (0 .. $#rows) { 
    $dbh->do("INSERT INTO sons (son, father) VALUES (?,?)", {}, $rows[$i][0], $rows[$i][1]); 
} 

our @sons_array; 
my $sth = $dbh->prepare("SELECT * FROM sons"); 
$sth->execute(); 
while (my $ref = $sth->fetchrow_hashref()) { 
    $sons_array[++$#sons_array] = Son->new($ref->{'son'}, $ref->{'father'}); 
} 
$sth->finish(); 
$dbh->disconnect(); 


print $q->header("text/html"),$q->start_html("Perl CGI"); 
print "\n\n"; 
constructFamilyTree(@sons_array, ''); 
print $q->end_html; 

sub constructFamilyTree { 
    my @sons_array = @_[0..$#_ -1]; 
    my $print_father; 
    my $print_son; 
    my $print_relation; 
    my $current_parent = @_[$#_]; 
    my @new_sons_array; 
    my @new_siblings; 

    #print $current_parent."\n"; 
    foreach my $item (@sons_array){ 
     if(!$item->{'son'} || $item->{'son'} eq $item->{'father'}) { # == ($item->{'son'} eq '') 
      print "\n List contains bad data\n"; 
      return 0; 
     } 

     if($item->{'father'} eq $current_parent) { 
      my $temp_print_relation; 
      foreach my $child (@sons_array) { 
       if($child->{'father'} eq $item->{'son'}) { 
        if(!$temp_print_relation) { 
         $temp_print_relation .= ' |'; 
        } 
        else { 
         $temp_print_relation .= '-----|'; 
        } 
       } 
      } 
      $print_relation .= $temp_print_relation." "; 
      $print_son .= '('.$item->{'son'}.') '; 
      @new_siblings[++$#new_siblings] = $item; 
      $print_father = $item->{'father'}; 
     } 
     else { 
      $new_sons_array[++$#new_sons_array] = $item; 
     } 
    } 

    print $print_son. "\n". $print_relation."\n"; 
    #print $print_father."\n"; 
    #print $print_relation . "\n". $print_son; 
    foreach my $item (@new_siblings) { 
     constructFamilyTree(@new_sons_array, $item->{'son'}); 
    } 
} 


perl module: 
#File Son.pm, module for class Son 

package Son; 

sub new { 
    my($class, $son, $father) = @_; 
    my $self = {'son' => $son, 
       'father' => $father}; 

    bless $self, $class; 
    return $self; 
} 

1; 
+4

"A corto di idee", idee per cosa esattamente? non c'è nessuna domanda qui, solo il tuo incarico, e un "qui, vai, fallo per me". –

+0

La tua domanda in realtà non riguarda CGI o MySQL. Si tratta di scegliere e visualizzare una struttura dati appropriata. Il tuo codice include troppi dettagli superflui per l'attività in corso. –

+0

Mi chiedo solo se sono completamente fuori o sulla strada giusta. Siamo spiacenti/Grazie. –

risposta

5

In attesa di chiarimenti su ciò che la domanda è, ho pensato di vedere che sei in una sorta di istituzione di apprendimento sempre dato le assegnazioni Perl correlati, ragionavo non c'è momento migliore per introdurre a Moose e CPAN, cose che dovresti davvero usare nel mondo reale.

Esso e le sue varie estensioni semplificheranno la vita e rendono il design orientato agli oggetti più semplice e manutenibile.

#!/usr/bin/perl 
use strict; 
use warnings; 
use Data::Dumper; 
use Moose::Autobox; 
use 5.010; 

sub Moose::Autobox::SCALAR::sprintf { 
    my $self = shift; 
    sprintf($self, @_); 
} 

{ 

    package Son; 
    use Moose; 
    use MooseX::Types::Moose qw(:all); 
    use MooseX::ClassAttribute; 
    use MooseX::Has::Sugar 0.0300; 
    use Moose::Autobox; 

    class_has 'Ancestry' => (isa => HashRef, rw, default => sub { {} }); 
    class_has 'People' => (isa => HashRef, rw, default => sub { {} }); 
    has 'name'   => (isa => Str,  rw, required); 
    has 'father'   => (isa => Str,  rw, required); 

    sub BUILD { 
    my $self = shift; 
    $self->Ancestry->{ $self->name } //= {}; 
    $self->Ancestry->{ $self->father } //= {}; 
    $self->People->{ $self->name }  //= $self; 
    $self->Ancestry->{ $self->father }->{ $self->name } = $self->Ancestry->{ $self->name }; 
    } 

    sub children { 
    my $self = shift; 
    $self->subtree->keys; 
    } 

    sub subtree { 
    my $self = shift; 
    $self->Ancestry->{ $self->name }; 
    } 

    sub find_person { 
    my ($self, $name) = @_; 
    return $self->People->{$name}; 
    } 

    sub visualise { 
    my $self = shift; 
    '<ul><li class="person">%s</li></ul>'->sprintf($self->visualise_t); 
    } 

    sub visualise_t { 
    my $self = shift; 
    '%s <ul>%s</ul>'->sprintf(
     $self->name, 
     $self->children->map(
     sub { 
      '<li class="person">%s</li>'->sprintf($self->find_person($_)->visualise_t); 
     } 
     )->join('') 
    ); 
    } 
    __PACKAGE__->meta->make_immutable; 
} 

my @rows = ([ "bill", "sam" ], [ "bob", "" ], [ "jack", "sam" ], [ "jone", "mike" ], [ "mike", "bob" ], [ "sam", "bob" ],); 

for (@rows) { 
    Son->new(
    father => $_->at(1), 
    name => $_->at(0), 
); 
} 

<<'EOX'->sprintf(Son->find_person('bob')->visualise)->say; 
<html> 
    <head> 
    <style> 
     li.person { 
border: 1px solid #000; 
padding: 4px; 
margin: 3px; 
background-color: rgba(0,0,0,0.05); 
     } 
    </style> 
    </head> 
    <body> 
    %s 
    </body> 
</html> 
EOX 
+0

Mi stavo chiedendo se qualcuno avesse qualche suggerimento su come eseguire meglio il compito a portata di mano. Non stavo cercando una mano. Grazie per la lezione Moose e CPAN, però! Sono nuovo di perl ed è ESTREMAMENTE utile sapere qual è il miglior metodo del mondo reale. Grazie ancora. –

1

Per quanto mi è piaciuto imparare da Kent Fredric's answer (vedi, io ho scritto poco nulla al di là di semplici esercizi che utilizzano Moose), immagino che si potrebbe imparare di più, cercando in una soluzione un po 'più tradizionale al problema della visualizzazione del struttura dati. Non risolve direttamente la tua domanda (presumo che la tua domanda sia basata su un compito a casa). Se il codice si rivela utile, sono certo che il tuo istruttore lo apprezzerebbe se citi qualsiasi aiuto esterno che hai ricevuto.

#!/usr/bin/perl 

use strict; 
use warnings; 

my @rows = (
    [ bill => 'sam' ], 
    [ bob => ''  ], 
    [ jack => 'sam' ], 
    [ jone => 'mike' ], 
    [ mike => 'bob' ], 
    [ sam => 'bob' ], 
    [ jim => ''  ], 
    [ ali => 'jim' ], 
); 

my %father_son; 

for my $pair (@rows) { 
    push @{ $father_son{ $pair->[1] } }, $pair->[0]; 
} 

for my $root (@{ $father_son{''} }) { 
    print_branch($root, 0); 
} 

sub print_branch { 
    my ($branch, $level) = @_; 
    print "\t" x $level, $branch, "\n"; 
    if (exists $father_son{$branch}) { 
     for my $next_branch (@{ $father_son{$branch} }) { 
      print_branch($next_branch, $level + 1); 
     } 
    } 
    return; 
} 

__END__ 

uscita:

C:\Temp> tkl 
bob 
     mike 
       jone 
     sam 
       bill 
       jack 
jim 
     ali 
+0

Questo sembra essere il più facile da capire per una persona che sta imparando perl (come me). Anche se, ieri sera, sono riuscito a mettere insieme una risposta, ho risolto il mio problema. Questa è anche una risposta molto più semplice al mio problema. Grazie! Imparerò da questo esempio! –

3

Usa GraphViz. È molto più facile che creare l'immagine da soli.

Problemi correlati