2009-07-09 11 views
5

Mam zadanie programowania w Perlu, który wymaga mnie aby wykonać następujące czynności:Jak mogę zbudować drzewo genealogiczne z Perlem?

  1. Tworzy tabelę w bazie danych MySQL, i wstawia te zapisy do niego:

  2. wczytuje dane z tabeli w szereg przykładów klasowego Syna.

  3. Użycie tablicy tworzy kod HTML reprezentujący drzewo ojciec-syn i wypisuje kod HTML na STDOUT. Nie jest konieczne, aby drzewo wyglądało dobrze. Coś jak to będzie w porządku:

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

biegnę z pomysłów, proszę o pomoc. Mój kod jest w następujący sposób:

#!/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

"Kończy się pomysł", pomysły na co dokładnie? tutaj nie ma wątpliwości, tylko twoje zadanie i "proszę, zrób to dla mnie". –

+0

Twoje pytanie tak naprawdę nie dotyczy CGI ani MySQL. Chodzi o wybranie i wyświetlenie odpowiedniej struktury danych. Twój kod zawiera zbyt wiele zbędnych szczegółów dla danego zadania. –

+0

Zastanawiam się, czy jestem całkowicie nie na dobrej drodze. Przepraszam/dzięki. –

Odpowiedz

5

Czekając na wyjaśnienie, co jest pytanie, pomyślałem widząc, że jesteś w jakiejś instytucji uczenia się coraz danego zadania Perl pokrewnych, ja uzasadniona nie ma lepszego czasu, aby wprowadzić Ty do Łosia i CPAN, rzeczy, których naprawdę powinieneś używać w prawdziwym świecie.

To i jego różne rozszerzenia ułatwią Ci życie i sprawią, że projektowanie zorientowane obiektowo będzie prostsze i łatwiejsze w utrzymaniu.

#!/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

Zastanawiałem się, czy ktoś ma jakieś sugestie, jak lepiej wykonać to zadanie. Nie szukałem strony. Dzięki za lekcję Łosia i CPAN! Jestem nowicjuszem w Perl i to jest bardzo pomocne, aby wiedzieć, jaka jest najlepsza metoda na świecie rzeczywistym. Dzięki jeszcze raz. –

1

Aż I cieszył uczenia się od Kent Fredric's answer (patrz, ja ledwo napisane niczego poza prostych ćwiczeń wykorzystujących Moose), I postać może nauczyć się więcej, patrząc na nieco bardziej tradycyjne rozwiązania problemu wyświetlające struktura danych. To nie rozwiązuje bezpośrednio twojego pytania (Przyjmuję, że twoje pytanie opiera się na zadaniu domowym). Jeśli kod okaże się pomocny, jestem pewien, że twój instruktor byłby wdzięczny, gdybyś zacytował jakąkolwiek zewnętrzną pomoc, którą otrzymałeś.

#!/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__ 

wyjściowa:

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

To wydaje się być najłatwiejsze do zrozumienia dla osoby uczącej się perla (jak ja). Chociaż udało mi się zebrać razem odpowiedź zeszłej nocy, która naprawiła mój problem. Jest to również znacznie prostsza odpowiedź na mój problem. Dzięki! Nauczę się z tego przykładu! –

3

Zastosowanie GraphViz. To znacznie łatwiejsze niż zrobienie tego samemu.

Powiązane problemy