Perl - 使用递归函数将数组的散列转换为数组的数组

Perl - Convert hash of arrays to array of arrays using recursive function

我在我的脚本中创建了以下数组散列(称为 $hoa):

$hoa = {
      'Continents' => [
                        'Continent1',
                        'Continent2',
                        'Continent3'
                      ],
      'Earth' => [
                   'Continents'
                 ],
      'Continent1' => [
                        'Country1'
                      ],
      'Continent3' => [
                        'Country3'
                      ],
      'Country1' => [
                      'City1',
                      'City2'
                    ]
    };

我想将其转换为数组数组,以便在脚本的后面部分使用。数组的数组应如下所示:

$aoa=[
    ['Earth','Continents','Continent1','Country1','City1'],
    ['Earth','Continents','Continent1','Country1','City2'],
    ['Earth','Continents','Continent2'],
    ['Earth','Continents','Continent3','Country3']
];

我创建了以下代码来完成这项工作,但它没有按预期工作。

sub CreateArrofArr
{
    my $arg={@_};
    my $member=$arg->{member};
    my $hoa=$arg->{hoa};

    my $aoa=[];

    if(exists($hoa->{$member}))
    {
        for(my $i=0; $i<scalar(@{$hoa->{$member}}); $i++)
        {
            my $elem=@{$hoa->{$member}}->[$i];

            my $temp_arr=[];
            if(!exists($hoa->{$elem}))
            {
                push(@{$temp_arr},$member);
                push(@{$temp_arr},$elem);
                push(@{$aoa},$temp_arr);

            }
           else
           {
                push(@{$aoa},@{CreateArrofArr(member=>$elem,hoa=>$hoa)})
           }
        }
    }
    return ($aoa);
}


my $aoa=CreateArrofArr(member=>"Earth",hoa=>$hoa);

print Dumper($aoa);

$aoa 返回如下(这不是我所期望的):

$VAR1 = [
      [
        'Country1',
        'City1'
      ],
      [
        'Country1',
        'City2'
      ],
      [
        'Continents',
        'Continent2'
      ],
      [
        'Continent3',
        'Country3'
      ]
    ];

请帮忙。

最小的变化:

sub CreateArrofArr {
    my $arg = { @_ };

    my $member = $arg->{member};
    my $hoa    = $arg->{hoa};

    my $aoa = [];
    if (exists($hoa->{$member})) {
        for (my $i=0; $i<scalar(@{$hoa->{$member}}); $i++) {
            my $elem = $hoa->{$member}->[$i];
            push @{$aoa},
                map { [ $member, @$_ ] }
                    @{ CreateArrofArr( member => $elem, hoa => $hoa ) };
        }
    } else {
        my $temp_arr = [];
        push @{$temp_arr}, $member;
        push @$aoa, $temp_arr;
    }

    return $aoa;
}

my $aoa = CreateArrofArr( member => "Earth", hoa => $hoa );

上面的清理版本:

sub flatten {
    my ($tree, $current) = @_;
    my $node = $tree->{$current};
    return [ $current ] if !$node;
    return
       map { [ $current, @$_ ] }
          map { flatten($tree, $_) }
            @$node;
}

my @flattened = flatten($tree, 'Earth');

另一种方法是将路径向下传递到树的根,而不是继续添加到您的路径。这稍微简化了事情。

sub flatten {
    my $tree = shift;
    my $node = $tree->{ $_[-1] };
    return [ @_ ] if !$node;
    return map { flatten($tree, @_, $_) } @$node;
}

my @flattened = flatten($tree, 'Earth');