my %hash=( 'MEX1J' => { desc => 'Job 2' , pred => ['TEX1J'], }, 'MEX2J' => { desc => 'Job end', pred => ['TROUBLE'], }, 'TEX1J' => { desc => 'Job start', pred => [], }, 'TROUBLE' => { desc => 'who cares', pred => ['MEX1J'] } ); sub pred_cmp { my ($i1, $i2) = @_; # Anybody with no preds is first if (@{$hash{$i1}{pred}} == 0) { return -1; } elsif (@{$hash{$i2}{pred}} == 0) { return 1; } # If one is a pred of the other, it's first elsif (grep {$_ eq $i2} @{$hash{$i1}{pred}}) { return 1; } elsif (grep {$_ eq $i1} @{$hash{$i2}{pred}}) { return -1; } else { # Check recursively my ($rec) = grep $_, map {pred_cmp($_, $i2)} @{$hash{$i1}{pred}}; if ($rec) { print "Returning $rec\n"; return $rec } ($rec) = grep $_, map {pred_cmp($i1, $_)} @{$hash{$i2}{pred}}; if ($rec) { print "Returning $rec\n"; return $rec } return 0; } } for (sort {pred_cmp($a,$b)} keys %hash) { print "$_\n"; }