2009-07-09 38 views
5

Tôi có một nhiệm vụ lập trình trong Perl đòi hỏi tôi phải làm như sau:Làm thế nào tôi có thể xây dựng một cây gia đình với Perl?

  1. Tạo một bảng trong một cơ sở dữ liệu mySQL, và chèn những hồ sơ này vào nó:

  2. tải dữ liệu từ bảng vào một loạt các trường hợp của lớp Son.

  3. Sử dụng mảng, tạo ra HTML code đại diện cho một cây cha-con trai, và in mã html để STDOUT. Nó không cần thiết để làm cho cây trông tốt. Một cái gì đó như thế này sẽ là tốt:

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

Tôi đang chạy ra khỏi ý tưởng, xin vui lòng giúp đỡ. Mã của tôi là như sau:

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

"Chạy ra khỏi ý tưởng", ý tưởng cho những gì chính xác? không có câu hỏi ở đây, chỉ là nhiệm vụ của bạn, và một "ở đây, hãy làm điều đó cho tôi". –

+0

Câu hỏi của bạn thực sự không phải về CGI hoặc MySQL. Đó là về việc lựa chọn và hiển thị một cấu trúc dữ liệu thích hợp. Mã của bạn bao gồm quá nhiều chi tiết thừa cho nhiệm vụ trong tầm tay. –

+0

Chỉ cần tự hỏi nếu tôi hoàn toàn tắt hoặc đi đúng hướng. Xin lỗi/Cảm ơn. –

Trả lời

5

Trong khi chờ đợi làm rõ như những gì câu hỏi là, tôi đã tìm thấy bạn đang ở trong một số loại hình tổ chức học tập bị cho bài tập liên quan Perl, tôi lập luận không có thời gian tốt hơn để giới thiệu bạn đến Moose và CPAN, những thứ bạn thực sự nên sử dụng trong thế giới thực.

Nó, và phần mở rộng khác nhau của nó, sẽ làm cho cuộc sống của bạn dễ dàng hơn, và làm cho đối tượng thiết kế hướng thẳng về phía trước nhiều hơn và duy trì.

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

Tôi chỉ tự hỏi nếu có ai có bất cứ đề nghị như thế nào để hoàn thành tốt hơn nhiệm vụ trong tầm tay. Tôi đã không tìm kiếm một bàn tay ra. Cảm ơn bài học Moose và CPAN! Tôi mới để perl và EXTREMELY hữu ích của nó để biết phương pháp thế giới thực tốt nhất là gì. Cảm ơn một lần nữa. –

1

Càng nhiều càng tốt Tôi rất thích học hỏi từ Kent Fredric's answer (xem, tôi đã hầu như không viết bất cứ điều gì ngoài bài tập đơn giản sử dụng Moose), tôi tìm bạn có thể tìm hiểu thêm bằng cách nhìn vào một giải pháp phần nào truyền thống hơn cho vấn đề hiển thị cấu trúc dữ liệu. Nó không trực tiếp giải quyết câu hỏi của bạn (tôi giả sử câu hỏi của bạn được dựa trên một bài tập về nhà). Nếu mã chứng minh là hữu ích, tôi chắc chắn người hướng dẫn của bạn sẽ đánh giá cao nếu bạn trích dẫn bất kỳ trợ giúp bên ngoài bạn đã nhận được.

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

Output:

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

này có vẻ là dễ dàng nhất để hiểu cho một người chỉ học perl (như bản thân mình). Mặc dù, tôi đã cố gắng trả lời một câu trả lời với nhau tối qua, điều đó đã khắc phục được vấn đề của tôi. Đây cũng là một câu trả lời đơn giản hơn nhiều cho vấn đề của tôi. Cảm ơn! Tôi sẽ học từ ví dụ này! –

3

Sử dụng GraphViz. Điều đó dễ hơn rất nhiều so với việc tự tạo hình.

Các vấn đề liên quan