6
votes

Comment puis-je construire un arbre généalogique avec Perl?

J'ai une mission de programmation à Perl qui me demande de faire ce qui suit:

  1. crée une table dans une base de données MySQL et insère ces enregistrements dans: P> li>

  2. charge les données de la table dans une gamme d'instances de fils de classe. P> li>

  3. Utilisation de la matrice, crée un code HTML représentant un arborescence de père-Son et imprime le code HTML à STDOUT. Il n'est pas nécessaire de faire paraître l'arbre. Quelque chose comme ça irait bien: p> li> ol>

     arbre P>

    Je suis à court d'idées, s'il vous plaît aider. strong> Mon code est comme suit: p>

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


4 commentaires

"Manquer d'idées", des idées pour quoi exactement? Il n'y a pas de doute ici, juste votre mission, et un "ici, ça va pour moi".


Votre question n'est vraiment pas à propos de CGI ou de MySQL. Il s'agit de choisir et d'afficher une structure de données appropriée. Votre code comprend trop de détails superflus pour la tâche à accomplir.


Je me demandais simplement si je suis complètement éteint ou sur la bonne voie. Désolé / merci.


Veuillez poster votre code fini comme réponse.


3 Réponses :


5
votes

En attendant des éclaircissements quant à la question de savoir quelle est la question, j'ai pensé à voir que vous êtes dans une sorte d'institution d'apprentissage reçoive des tâches connexes de Perl, je suis raisonné, il n'y a pas de meilleur moment pour vous présenter Moose et CPAN, des choses que vous devriez vraiment être utiliser dans le monde réel.

IT, et ses diverses extensions, vous faciliteront votre vie et rend la conception orientée objet plus simple et maintenue. P>

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


1 commentaires

Je me demandais simplement si quelqu'un avait des suggestions sur la manière de mieux accomplir la tâche à accomplir. Je ne cherchais pas une distribution. Merci pour la leçon d'orignal et de cpan, cependant! Je suis nouveau à Perl et c'est extrêmement utile de savoir quelle est la meilleure méthode du monde réel. Merci encore.



1
votes

Autant que j'ai apprécié l'apprentissage de Réponse de Kent Fredric (voir, J'ai à peine écrit quoi que ce soit au-delà des exercices simples utilisant Moose), je pense que vous pourriez en apprendre plus en regardant une solution quelque peu traditionnelle au problème de l'affichage de la structure de données. Il ne résout pas directement votre question forte> (je suppose que votre question est basée sur une mission de devoirs). Si le code s'avère utile, je suis sûr que votre instructeur l'apprécierait si vous citez n'importe quelle aide extérieure que vous avez reçue.

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


1 commentaires

Cela semble être le plus facile à comprendre pour une personne qui apprend simplement Perl (comme moi-même). Bien que j'ai réussi à joindre une réponse ensemble hier soir, qui a corrigé mon problème. C'est aussi une réponse beaucoup plus simple à mon problème. Merci! J'apprendrai de cet exemple!



3
votes

Utilisez graphviz . C'est beaucoup plus facile que de faire la photo vous-même.


0 commentaires