このブログを検索

2010/10/31

動的に二次元配列を作成する

$ref_array1 = [apple, banana, cherry, donkey];
$ref_array2 = [monkey, dog, cat, fish, horse, sheep];

push(@a,$ref_array);
push(@a,$ref_array2);

このようにして、配列のリファレンスを変数に格納し、それを配列にpushしていくことはできる。

しかし、STDINとか、ファイルを読むとかして作る配列を、同じようにpushできない。

while(){
    chomp;
    @b=split / /, $_;
    push (@a,@b);
}


こういう風にすると、単に配列を追加するだけになる。そうではなくて、2次元配列にしたい。

dog cat horse
orange banana apple


と入力したら、

@a=([dog cat horse],[orange banana apple]);


という配列にしたいのである。

while(){
    chomp;
    @b=split / /, $_;
    $ref=\@b;
    push (@a,$ref);
}

for $i (0 .. $#a) {
    for $j (0 .. $#{$a[$i]}) {
        print '$a[' . $i . '][' . $j . ']=' . $a[$i][$j] . '   ';
    }
    print "\n";
}





固定文字列のときは、スカラー変数に[]で囲った配列を代入し、そのスカラー変数を配列にpushしたから、

$ref=\@b


として、それを同じように配列にpushしたらできるのかと思ったら、

a b c
d e f
^Z

$a[0][0]=d   $a[0][1]=e   $a[0][2]=f
$a[1][0]=d   $a[1][1]=e   $a[1][2]=f


という風になってしまう。2行目は望みどおりの結果なのだが、1行目も2行目と同じになってしまっている。


「スカラー変数」
「配列」
「リファレンス」
「[]で囲って,で区切ったた複数の文字列」
「()で囲って,で区切った複数の文字列」
「配列に\をつけたもの \@array」
「スカラー変数に\をつけたもの \$var」

これらの意味がよくわからず混同している。

[]で囲った文字列を「無名配列」と呼び、

$ref = ["apple", "orange", "banana"];

のようにした時、$ref に代入されるのは「無名配列へのリファレンス」だそうだ。

つまり、$ref には配列そのものの値が入っているのではなく、配列へのポインタが入っている。だから、さっきのスクリプトでSTDINが2行入力されたときに、1行目のポインタの内容が2行目で上書きされ、@aに入っているポインタが指す内容が同じになる、というわけか。

じゃあどうすればいいのか・・・。リファレンスについては、「続・はじめてのPerl」に書いてあるそうだ。買わなきゃだめか・・・。

while () {
    chomp();
    push(@a, [ split(" ") ]);
}

for $i (0 .. $#a) {
    for $j (0 .. $#{$a[$i]}) {
        print '$a[' . $i . '][' . $j . ']=' . $a[$i][$j] . '   ';
    }
    print "\n";
}

とりあえずこれで、やりたいことはできた。某所からの丸パクリであるが。