ブログが続かないわけ

この日記のはてなブックマーク数
Webエンジニアが思うこと by junichiro on Facebook

[Perl][PHP]配列に値を追加するときはpush を使うけど、Perl とPHP では微妙に異なる

このエントリーを含むはてなブックマーク hateb
スタック(要は配列)の一番後ろに値を追加するのは、push という操作になる。Perl ではpush という関数があるし、PHP ではarray_push という関数がある。ところが、Perl とPHP ではこれらの関数の使い方、挙動が若干異なるので、簡単にまとめておく。push 以外の配列操作関数(pop, shift, unshift)もほとんど同じ考え方なので、これが参考になると思う。
array1: a, b, c
array2: d, e, f
こういう3つの要素を持つ、1次元の2つの配列があるとする。これらの配列を用いて、2次元の配列を作りたいときにPerl, PHP ではそれぞれどのように書けばいいのだろうか。

Perl
Perl では厳密には多次元配列を扱うことはできない。配列の要素に、配列のリファレンス(これ自体はスカラー値)を持たせることで、擬似的に多次元配列を表現する。慣れてしまえば、多次元配列を扱う感覚で、問題なく使える。さきほどの問題の解答はこうだ。
# 配列定義
my @array1 = ('a', 'b', 'c');
my @array2 = ('d', 'e', 'f');

# 2次元に連結(push を使う)
my @res;
push(@res, ¥@array1, ¥@array2);
これで@res には2次元配列が格納された。
$VAR1 = [
[
'a',
'b',
'c'
],
[
'd',
'e',
'f'
]
];
push の引数にはLIST をとることができるので、リファレンスにした@array1 と@array2 を順番に格納している。多次元配列を表現するために、リファレンスにしているところがポイントだ。

PHP
PHPは多次元配列を扱えるので、リファレンスなどを考える必要はない。こう書けば良い。
# 配列定義
$array1 = array('a', 'b', 'c');
$array2 = array('d', 'e', 'f');

# 2次元に連結(push を使う)
$res = array();
array_push($res, $array1, $array2);
array_push の引数に配列をそのまま渡していることに注意してほしい。

では、今度は最初に与えられた配列を直列に連結した下記のような配列を作りたいときはどうすればいいのだろうか。
res: a, b, c, d, e, f

Perl
Perl では簡単だ。
# 直列に連結
my @res;
push(@res, @array1, @array2);
push にあたえる引数をリファレンスにしなければ、それぞれLIST として展開されるため、これで@res は要素を6つ持つ1次元配列になる。
$VAR1 = [
'a',
'b',
'c',
'd',
'e',
'f'
];

PHP
PHPではarray_push にあたえる引数はとくに展開されたりすることはないので、array_push では実現できない。こういうことをやりたい場合は、array_merge という別の関数の力を借りる必要がある。
# 直列に連結
$res1 = array();
$res1 = array_merge($array1, $array2);
Array
(
[0] => a
[1] => b
[2] => c
[3] => d
[4] => e
[5] => f
)
array_push を使ったときの失敗例は各自で確認してみてほしい。

ちなみに、いまは説明の便宜上res という新しい変数で結果を取得しているが、もとのarray1 にarray2 を直列に連結させたければ、Perl/PHP それぞれでの書き方はこうなる。

Perl
push(@array1, @array2);

PHP
$array1 = array_merge($array1, $array2);

push は第1引数で与えられた配列に影響を与えるのに対して、array_merge では引数で与えられた変数には影響を与えず、戻り値として結果を返すというところが異なるのがわかる。Perl とPHP は「似たように書けるけど、実は結果が異なる」というものがいくつかあるので、PHP とPerl の両方を触る場合は注意しなければならない。
この記事のトラックバックURL
http://en.yummy.stripper.jp/trackback/1168151
トラックバック
コメント









関連情報