my $input = { 'Sally Smith' => { parents => ['Bob Smith', 'Rhonda Smith']}, 'Betty Freeman' => { parents => ['Earl Freeman', 'Harmony Ellis']}, 'Betty Boop' => { parents => ['Rhonda Smith', 'Louis McFern']}, 'Jim Morris' => { parents => ['Betty Boop', 'John Wayne']}, }; #### my $people = {}; for my $m (keys %$input) { add_person($people,$m, parents => $input->{$m}{parents}); for my $p (@{ $input->{$m}{parents} }) { add_person($people,$p,children => $m); } } sub add_person { my ($people,$name,%params) = @_; if(! defined $people->{$name}) { $people->{$name} = { children => [], parents => [] }; } for my $par (keys %params) { push @{ $people->{$name}{$par} }, ref($params{$par}) eq "ARRAY" ? @{$params{$par}} : $params{$par}; } } #### { "Betty Boop" => { children => ["Jim Morris"], parents => ["Rhonda Smith", "Louis McFern"], }, "Betty Freeman" => { children => [], parents => ["Earl Freeman", "Harmony Ellis"] }, "Bob Smith" => { children => ["Sally Smith"], parents => [] }, "Earl Freeman" => { children => ["Betty Freeman"], parents => [] }, "Harmony Ellis" => { children => ["Betty Freeman"], parents => [] }, "Jim Morris" => { children => [], parents => ["Betty Boop", "John Wayne"] }, "John Wayne" => { children => ["Jim Morris"], parents => [] }, "Louis McFern" => { children => ["Betty Boop"], parents => [] }, "Rhonda Smith" => { children => ["Sally Smith", "Betty Boop"], parents => [] }, "Sally Smith" => { children => [], parents => ["Bob Smith", "Rhonda Smith"] }, } #### for my $top_level (sort keys %$people) { next if @{ $people->{$top_level}{parents} }; print_level($people,$top_level,0); } sub print_level { my ($people,$name,$level) = @_; print " "x$level,$name,"\n"; for my $child (@{ $people->{$name}{children} }) { print_level($people,$child,$level+1); } } #### Bob Smith Sally Smith Earl Freeman Betty Freeman Harmony Ellis Betty Freeman John Wayne Jim Morris Louis McFern Betty Boop Jim Morris Rhonda Smith Sally Smith Betty Boop Jim Morris