简体   繁体   English

如何用Perl构建一个家谱?

[英]How can I construct a family tree with Perl?

I have a programming assignment in Perl that requires me to do the following: 我在Perl中有一个编程任务,要求我执行以下操作:

  1. Creates a table in a mySQL database, and inserts these records into it: 在mySQL数据库中创建一个表,并将这些记录插入其中:

  2. Loads the data from the table into an array of instances of class Son. 将表中的数据加载到Son类的实例数组中。

  3. Using the array, creates HTML code representing a father-son tree, and prints the html code to STDOUT. 使用该数组,创建表示父子树的HTML代码,并将html代码打印到STDOUT。 It's not necessary to make the tree look good. 没有必要让树看起来很好。 Something like this would be fine: 这样的东西会很好:

树

I'm running out of ideas, please help. 我的想法已经用完了,请帮忙。 My code is as follows: 我的代码如下:

#!/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: $@\n" if $@;

$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;

While awaiting clarification as to what the question is, I figured seeing you're in some sort of learning institution getting given Perl related assignments, I reasoned there's no better time to introduce you to Moose and CPAN, things you really should be using in the real world. 在等待澄清问题的同时,我想看到你在某种学习机构中获得了Perl相关的任务,我认为没有比这更好的时间向你介绍Moose和CPAN,你真正应该在真实世界。

It, and its various extensions, will make your life easier, and makes Object Oriented design more straight forward and maintainable. 它及其各种扩展将使您的生活更轻松,并使面向对象的设计更直接和可维护。

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

Use GraphViz . 使用GraphViz That's a lot easier than making the picture yourself. 这比自己制作图片要容易得多。

As much as I enjoyed learning from Kent Fredric's answer (see, I have barely written anything beyond simple exercises using Moose), I figure you might learn more by looking at a somewhat more traditional solution to the problem of displaying the data structure. 尽管我很高兴听到肯特弗雷德里克的答案 (看,我几乎没有用Moose写过简单的练习),但我想通过研究一种更传统的解决方案来解决显示数据结构的问题。 It does not directly solve your question (I assume your question is based on a homework assignment). 它没有直接解决你的问题 (我假设你的问题是基于家庭作业)。 If the code proves to be helpful, I am sure your instructor would appreciate it if you cite any outside help you have received. 如果代码证明是有用的,我相信如果您引用任何外部帮助,您的教练会很感激。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用bash或Perl脚本遍历目录树? - How can I traverse a directory tree using a bash or Perl script? 如何用Perl杀死整个进程树? - How can I kill a whole process tree with Perl? 如何在Perl程序中打印所有函数的语法树? - How can I print the syntax tree of all functions in a Perl program? 如何使用Perl的YAML :: Tiny走YAML树? - How can I walk a YAML tree with Perl's YAML::Tiny? 如何从Perl中的coderef获取语法树? - How can I get the syntax tree from a coderef in Perl? 如何在Perl中构建与OS无关的文件路径,包括可选的Windows驱动器号? - How can I construct OS-independent file paths in Perl including an optional Windows drive letter? 如何使用Perl的三元条件运算符构造复数形式的单词? - How can I construct plural forms of words using Perl's ternary conditional operator? 我如何从csv文件读取数据并将其存储在二进制树中并在perl中写入多个文件 - how can i read data from csv file and store in binary tree and write multiple file in perl 如何使用Perl的XML :: LibXML将XML DOM树保存到新文档中? - How can I save an XML DOM tree to a new document using Perl's XML::LibXML? 我可以将Perl依赖项解压缩到本地树(例如Ruby on Rails)吗? - Can I unpack Perl dependencies to the local tree (like Ruby on Rails)?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM