使用perl按依赖性排序数组

caj*_*ine 11 sorting algorithm perl cpan graph

有一系列哈希,

my @arr = get_from_somewhere();
Run Code Online (Sandbox Code Playgroud)

@arr内容(例如)是:

@arr = (
  { id => "id2",    requires => 'someid', text => "another text2" },
  { id => "xid4",   requires => 'id2',    text => "text44" },
  { id => "someid", requires => undef,    text => "some text" },
  { id => "id2",    requires => 'someid', text => "another text2" },
  { id => "aid",    requires => undef,    text => "alone text" },
  { id => "id2",    requires => 'someid', text => "another text2" },
  { id => "xid3",   requires => 'id2',    text => "text33" },
);
Run Code Online (Sandbox Code Playgroud)

需要这样的东西:

my $texts = join("\n",  get_ordered_texts(@arr) );
Run Code Online (Sandbox Code Playgroud)

soo需要写一个sub text从散列中返回s 的数组, - 依赖顺序,所以从上面的例子中得到:

"some text",     #someid the id2 depends on it - so need be before id2
"another text2", #id2    the xid3 and xid4 depends on it - and it is depends on someid
"text44",        #xid4   the xid4 and xid3 can be in any order, because nothing depend on them
"text33",        #xid3   but need be bellow id2
"alone text",    #aid    nothing depends on aid and hasn't any dependencies, so this line can be anywhere
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,在@arr中可以是一些重复的"行",(上例中的"id2"),只需要输出任何一个id.

尚未提供任何代码示例,因为不知道如何开始.;(存在一些可用于解决方案的CPAN模块?

任何人都能指出我正确的方向吗?

ike*_*ami 13

使用图表:

use Graph qw( );

my @recs = (
   { id => "id2",    requires => 'someid', text => "another text2" },
   { id => "xid4",   requires => 'id2',    text => "text44" },
   { id => "someid", requires => undef,    text => "some text" },
   { id => "id2",    requires => 'someid', text => "another text2" },
   { id => "aid",    requires => undef,    text => "alone text" },
   { id => "id2",    requires => 'someid', text => "another text2" },
   { id => "xid3",   requires => 'id2',    text => "text33" },
);

sub get_ordered_recs {
   my %recs;
   my $graph = Graph->new();
   for my $rec (@_) {
      my ($id, $requires) = @{$rec}{qw( id requires )};

      $graph->add_vertex($id);
      $graph->add_edge($requires, $id) if $requires;

      $recs{$id} = $rec;
   }

   return map $recs{$_}, $graph->topological_sort();
}

my @texts = map $_->{text}, get_ordered_recs(@recs);
Run Code Online (Sandbox Code Playgroud)