1

perl 修道士の皆さん、

私はまだ正しく逆参照する方法について頭を悩ませています。(私は投稿する前に同様の投稿を読みましたが、残念ながらまだ概念が少し曇っています。)

次の配列があります。これは内部的に 2 つの配列で構成されています。(ところで、厳密な警告プラグマを使用しています。)

use strict; use warnings;
my @a1; my @a2;

どこ:

@a1 = ( "1MB", "2MB", ... )

と..

@a2 = ( "/home", "/home/debug", ... )

@a1 と @a2 は両方とも、51 行を含む配列です。したがって、これらを 2 番目の配列に入力します。

my @b;
push (@b, [ @a1, @a2 ]);

ただし、@b の結果を印刷しようとすると:

sub newl { print "\n"; print "\n"; }
my $an1; my @an1;
$an1 = $#a1;
@an1 = ( 0, 1..$an1 );

for my $i (@an1) { print @b[$i]; &newl; }

配列への参照が表示されます。

ARRAY(0x81c0a10)
  .
ARRAY(0x81c0a50)
  .
  .
  .

この配列を正しく印刷するにはどうすればよいですか? 配列を逆参照する必要があることはわかっていますが、これを行う方法がわかりません。私は自分の配列を次のように設定しようとしました:

push (@b, [ \@a1, \@a2 ]);

同じ結果が得られます。私も試しました:

for my $i (@an1) { print @{$b[$i]}; &newl; }

配列参照として 0 を使用することによる残念なエラーはどれですか?

Can't use string ("0") as an ARRAY ref while "strict refs" in use at p_disk_ex6.pl line 42.

どんな提案でも大歓迎です!

4

3 に答える 3

1

あなたを助けるかもしれない短いサンプルプログラム:

use strict;
use warnings;

my @a1 = qw(1MB 2MB 10MB 7MB);
my @a2 = qw(/foo /bar /flub /blub);

my @b = (\@a1, \@a2);
# equivalent long version:
# my @b = ();
# $b[0] = \@a1;
# $b[1] = \@a2;

for (my $i = 0; $i <= $#a2; $i++) {
    print "a1[$i]: $b[0][$i]\n";
    print "a2[$i]: $b[1][$i]\n";
    print "\n";
}

あなたの例では、匿名の配列参照 [] を @b にプッシュしていました。したがって、$b[0] には配列参照が含まれていました。

my @b;
push (@b, [ \@a1, \@a2 ]);
# this corresponds to:
# $b[0][0] = \@a1;
# $b[0][1] = \@a2;

[@a1, @a2] と記述した例では、結合された配列 @a1 と @a2 (最初に @a1 のすべての要素、次に @a2 のすべての要素) を含む array_ref を作成していました。

my @b;
push(@b , [@a1, @a2]);
# $b[0] = ['1MB' , '2MB', '10Mb', '7MB', '/foo', '/bar', '/flub', '/blub']
于 2012-08-08T14:00:57.280 に答える
0

各サブ配列に要素がいくつあるかを想定せず、任意のレベルのネストも許可する一般的なソリューションが必要な場合は、他の誰かが再帰データを表示するために既に作成したパッケージを使用することをお勧めします構造。特に一般的なのは YAML です。まだ持っていない場合は、cpan を実行してインストールできます。

$ cpan
Terminal does not support AddHistory.

cpan shell -- CPAN exploration and modules installation (v1.9800)
Enter 'h' for help.

cpan[1]> install YAML

そうすれば、任意のデータ構造を簡単に表示できます。簡単な例で説明するには:

use YAML;

my @a1 = qw(1MB 2MB 10MB 7MB);
my @a2 = qw(/foo /bar /flub /blub);

my @b = (\@a1, \@a2);

print Dump(\@b);

出力の結果

---
-
  - 1MB
  - 2MB
  - 10MB
  - 7MB
-
  - /foo
  - /bar
  - /flub
  - /blub

もう少し複雑な例

my @b = (\@a1, \@a2,
         { a => 0, b => 1 } );

与える

---
-
  - 1MB
  - 2MB
  - 10MB
  - 7MB
-
  - /foo
  - /bar
  - /flub
  - /blub
- a: 0
  b: 1

これを読み取るには、列 1 の 3 つの「-」文字は、3 つの要素を持つ配列を示します。最初の 2 つの要素には、それぞれ 4 つのサブ要素があります (3 列目に「-」がある行)。3 番目の外側の要素は、「キー: 値」のペアで構成されているため、ハッシュ参照です。

YAML の優れた機能は、サブルーチン参照を含むものを除いて、再帰的なデータ構造をファイルにダンプし、後で Load を使用して読み戻すことができることです。

独自の表示ルーチンをロールバックする必要がある場合、それは確かに可能ですが、再帰的に記述した方がはるかに簡単になります。ref を使用して、引数が配列参照かハッシュ参照 (またはスカラー参照) かを確認できます。

my @a1 = qw(1MB 2MB 10MB 7MB);
my @a2 = qw(/foo /bar /flub /blub);

my @b = (\@a1, \@a2,
         { a => 0, b => 1 } );

print_recursive(\@b);
print "\n";

sub print_recursive {
    my ($obj) = @_;

    if (ref($obj) eq 'ARRAY') {
        print "[ ";
        for (my $i=0; $i < @$obj; $i++) {
            print_recursive($obj->[$i]);
            print ", " if $i < $#$obj;
        }
        print " ]";
    }
    elsif (ref($obj) eq 'HASH') {
        print "{ ";
        my @keys = sort keys %$obj;
        for (my $i=0; $i < @keys; $i++) {
            print "$keys[$i] => ";
            print_recursive($obj->{$keys[$i]});
            print ", " if $i < $#keys;
        }
        print " }";
    }
    else {
        print $obj;
    }
}       

出力を生成する

[ [ 1MB, 2MB, 10MB, 7MB ], [ /foo, /bar, /flub, /blub ], { a => 0, b => 1 } ]

きれいな印刷を心配するためにサンプル コードを書いたり、スカラー、サブルーチン、または bless されたオブジェクト参照を処理したりしませんでしたが、かなり一般的な再帰的なデータ構造ダンパーをどのように書くことができるかについてのアイデアを与えるはずです。

于 2014-04-12T03:34:19.447 に答える
0

単純にこれも機能します

use strict;
use warnings;

my @a1 = qw(1MB 2MB 10MB 7MB);
my @a2 = qw(/foo /bar /flub /blub);

my @b = (@a1, @a2);
print "@b";
于 2013-02-26T20:53:13.530 に答える