【问题标题】:Recursive function in perlperl中的递归函数
【发布时间】:2016-05-02 09:27:16
【问题描述】:

我有一个类似的文件

abc->bcd, efg, hij
bcd->ijk, lmn, ipl
efg->kfg, iop, nkl
lmn->opq, stv, imn

嵌套的输出应该是这样创建的

abc
 bcd
  ijk
  lmn
    opq
    stv
    imn
    ipl
 efg
   kfg
   iop
   nkl
 hij

我不太确定如何在 perl 中使用递归函数来处理这个问题以找到任何级别的嵌套。非常感谢任何人的帮助。

我尝试过使用以下代码,但它只提供了一个级别

my $k = 0;
while ($k <=$#array1)
{
 if ($array1[$k]=~m/(.[^->]*)->(.[^\n]*)/)
 {
   $val = $1;
   $val1 = $2;
   push @check, $val;
   print $val;
   my @array2=split /,/,$val1;
   foreach my $newid (@array2)
    {
    push @check1, $newid;
    print $newid, "\n";
    }
 }
 $k++;

}

【问题讨论】:

  • 提供这么写的代码,在这方面帮助你

标签: perl recursion


【解决方案1】:

这是另一个有向图!他们最近似乎很受欢迎

您需要Graph 模块,它允许您构建一棵由edgesvertices(节点和连接)组成的树,然后遍历它以获取打印输出

此程序对您的示例数据执行此操作。构建图后,我会测试它是否是循环的,以避免无限循环,然后为所有源顶点调用我的递归子例程 print_vertex

源顶点是具有后继者但没有前驱者(子节点但没有父节点)的节点。所以它是树的根。我使用了for 循环,以防数据有多个根,但您的数据只有一个这样的顶点:abc

use strict;
use warnings 'all';
use feature 'say';

use Graph;

my $g = Graph->new(directed => 1);

while ( <DATA> ) {
    my ($from, @to) = /[^\s>,-]+/g;
    $g->add_edge($from, $_) for @to;
}

if ( my @cycle = $g->find_a_cycle ) {
    die sprintf "Graph contains a cycle: %s\n", join(' >> ', @cycle, $cycle[0]);
}

print_vertex($_) for $g->source_vertices;


sub print_vertex {
    my ($v, $indent) = (@_, 0);
    printf "%s%s\n", '  ' x $indent, $v;
    print_vertex($_, $indent+1) for $g->successors($v);
}


__DATA__
abc->bcd, efg, hij
bcd->ijk, lmn, ipl
efg->kfg, iop, nkl
lmn->opq, stv, imn

输出

abc
  efg
    iop
    kfg
    nkl
  bcd
    lmn
      stv
      opq
      imn
    ijk
    ipl
  hij

【讨论】:

  • 非常感谢 Borodin,当我尝试这个时,输出中的顺序发生了变化……你能帮我看看如何保留这些订单吗?
  • @Senthil 想到的第一个想法是在边缘添加权重。
  • @Senthil:这是基本要求吗?这是可以通过使用对每个顶点的数组的引用而不是简单的字符串来实现的。或者,如果仅按字母顺序而不是它们在输入数据中出现的顺序显示节点是可以接受的,您可以在 print_vertex 子例程中添加一个 sort
  • @Borodin,你能帮我把它变成一个订单吗,我正在努力实现但不能......非常感谢你的帮助
【解决方案2】:

...当我尝试这个时,输出中的顺序已经改变...你能 帮我看看如何保留订单?

纯 Perl sans 模块中的递归解决方案:

use strict;
use warnings;

my %children;
my $patriarch;

while (<DATA>) {
    chomp;
    my ($parent, @children) = split /[->, ]+/;
    $children{$parent} = \@children;
    $patriarch = $parent unless defined $patriarch;
}

sub print_family {
    my ($parent, $indentation) = (@_, '');

    print($indentation, $parent, "\n");

    if (exists($children{$parent})) {
        foreach my $child (@{$children{$parent}}) {
            &print_family($child, $indentation . "\t");
        }
    }
}

&print_family($patriarch)

__DATA__
abc->bcd, efg, hij
bcd->ijk, lmn, ipl
efg->kfg, iop, nkl
lmn->opq, stv, imn

生产:

abc
    bcd
        ijk
        lmn
            opq
            stv
            imn
        ipl
    efg
        kfg
        iop
        nkl
    hij

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-01
    相关资源
    最近更新 更多