Вложенная структура Perl: рекурсивная функция

Как продолжение моего предыдущего поста здесь!

Я проверил алгоритм с вложенными ссылками хеша:

Алгоритм:

use strict;
use warnings;

&expand_references2([a,b,{c=>123},d]);

sub expand_references2 {
  my $indenting = -1;
  my $inner; $inner = sub {
    my $ref = $_[0];
    my $key = $_[1];
    $indenting++;
    if(ref $ref eq 'ARRAY'){
      print '  ' x $indenting;
      printf("%s\n",($key) ? $key : '');
      $inner->($_) for @{$ref};
    }elsif(ref $ref eq 'HASH'){
      print '  ' x $indenting;
      printf("%s\n",($key) ? $key : '');
      for my $k(sort keys %{$ref}){
        $inner->($ref->{$k},$k);
      }
    }else{
      if($key){
        print '  ' x $indenting,$key,' => ',$ref,"\n";
      }else{
        print '  ' x $indenting,$ref,"\n";
      }
    }
    $indenting--;
  };
  $inner->($_) for @_;
}

В некоторых случаях отступ и символ новой строки не отображаются должным образом:

Example1:

expand_references2(hash=>{
                          d1=>{a=>123,
                               b=>234},
                          d2=>[1,2,3],
                          d3=>'hello'});

Выход:

Hash
<newline>                 # not required                                                                                                                                                                                                               
  d1                                                                                                                                                                                                           
    a => 123                                                                                                                                                                                                   
    b => 234                                                                                                                                                                                                   
  d2                                                                                                                                                                                                           
    1                                                                                                                                                                                                          
    2                                                                                                                                                                                                          
    3                                                                                                                                                                                                          
  d3 => hello

Вместо этого я бы предпочел вывод что-то вроде этого:

Hash
  d1                                                                                                                                                                                                           
    a => 123                                                                                                                                                                                                   
    b => 234                                                                                                                                                                                                   
  d2                                                                                                                                                                                                           
    1                                                                                                                                                                                                          
    2                                                                                                                                                                                                          
    3                                                                                                                                                                                                          
  d3 => hello

ИЛИ ЖЕ

Hash
  d1                                                                                                                                                                                                           
    a => 123                                                                                                                                                                                                   
    b => 234                                                                                                                                                                                                   

  d2                                                                                                                                                                                                           
    1                                                                                                                                                                                                          
    2                                                                                                                                                                                                          
    3                                                                                                                                                                                                          

  d3 => hello

Example2:

expand_references2([a,b,{c=>123},d]);

выход:

a
b
  c=>123           # indentation not required
d

Любое руководство о том, как достичь вышеизложенного в сценарии или сделать правильный отступ без лишних переносов строки?

Ценю любую помощь.

Спасибо

1 ответ

Я бы использовал несколько иной подход:

sub prindent {
  my( $ref, $ind ) = @_;
  if( ref( $ref ) eq 'HASH' ){
    for my $key (sort keys %{$ref}){
      print '  ' x $ind, $key;
      my $val = $ref->{$key};
      if( ref( $val ) ){
        print "\n";
        prindent( $val, $ind + 1 );
      } else {
        print " => $val\n";
      }
    }
  } elsif( ref( $ref ) eq 'ARRAY' ){
    for my $el ( @{$ref} ){
      if( ref( $el ) ){
        prindent( $el, $ind + 1 );
      } else {
        print '  ' x $ind, "$el\n";
      }
    }
  }
}
sub prindent2 {
  my( $key, $val ) = @_;
  if( defined $val ){
    print "$key\n";
    prindent( $val, 1 );
  } else {
    prindent( $key, 0 );
  }
}

Это производит:

hash
  d1
    a => 123
    b => 234
  d2
    1
    2
    3
  d3 => hello

a
b
  c => 123
d

Вам может не понравиться вывод для многомерных массивов: все элементы находятся в одном столбце.

Другие вопросы по тегам