Perl/CGIプログラムの配列操作
今回は、配列変数をいろいろな形で操作するということを学習していきましょう。
編集前記
今回の編集前記は、プログラミング技術上達には欠かすことのできない考え方についてのお話をしていこうと思います。
そのまえに、まずあなたにお聞きします。
プログラミング技術を上達させる最も大切な要素って何だと思いますか?
ちょっと考えてみてください。
よくわからない場合は、 Perl/CGIプログラム学習 において一番大切なことは何だろうと置き換えて考えていただいてもかまいません。
つまり、「プログラミングという世界の中で、最も学習してほしいポイントはどこだと思いますか?」ということですね。
なんだと思いますか?
関数をたくさん知っていることでしょうか?
理解しやすいプログラムコードを書くことでしょうか?
それとも、実行速度の速いプログラムコードを書くことでしょうか?
いろいろな答えが出たところで、個人的な意見を述べておくと…。
上記3つの答えはそれぞれとても大切ですが、もっと根本的な部分です。
それは、「物事の構造をイメージする力をつけること」です。
これはいまさら改めて言うことではなく、社会生活を営む上で普通に必要なことですが、プログラミングの世界では特に必要な思考の進め方ではないかと感じています。
もちろん前述の3つの要素もとても大切です。
関数をたくさん知っているということは、単純に同じ動作でもバリエーション豊富なプログラムコードを書けるということにつながります。
人間でたとえて言うなら言葉をたくさん知っていることと同じですから、難しい表現から簡単な表現まで、その場に応じた会話ができるということです。
わかりやすいプログラムコードを書くことも大切ですね。
わかりやすいプログラムコードというのは、自然とプログラミングミスも少なくなり、結果的にバグを減らしてくれます。
そして、実行速度の速いプログラムコードを書くことも大切です。
Perl/CGIプログラムにはたくさんのユーザーがアクセスしてきますから、1回の動作時間を短くすることはインターネットサーバーの負荷軽減につながります。
そして私が大切だと思っている「物事の構造をイメージする力をつけること」とは、いろいろな場面で必要とされますが、プログラミングの世界では特に大切です。
なぜなら、物事をイメージでとらえるということは、本当にそのものを理解していないとイメージ化することは難しいからですね。
例えばあなたが、見たことも聞いたこともないものを描こうとしても描けないのと同じです。
空想上の生き物とは、既存の生き物の組み合わせにすぎませんし、すでにあるものの組み合わせだからこそ他人にも理解できるのです。
イメージ化の話でもっとわかりやすい例を挙げるなら、あなたは丸暗記ってしたことありますか?
きっとほとんどの人が、学生時代に一度ぐらいは経験したことあると思います。
この丸暗記した状態というのが、今お話しているイメージ化に近い状態です。
例えばあなたが、A4ノート10ページ分の数学を丸暗記して試験に臨んだとします。
テスト勉強の日数は短いですが、毎日数時間集中して勉強したおかげで、頭の中にはあのA4ノートの映像とともに、そこに書かれている問題と答えが映っています。
そして試験当日、あなたはテスト問題を見た瞬間、これと似たような問題は…。
「確か、5ページ目の下の方に図と一緒に書いてあったな」などと、問題の解き方と一緒にあのノートのイメージがわいてくるはずです。
これがイメージ化する力ですね。
何度も同じノートを使って暗記したからこそ、ページ数まで浮かんできたわけです。
さらに、同じイメージ化されたものの中でも、文章をイメージ化したのと図形をイメージ化したのでは、図の方が圧倒的にたくさんの情報量をさばくことができます。
数学の図形問題などがよい例ですね。
あの図形問題を、図形を一切使わずにすべて文章で表現したとしたら、問題を作る側も説く側もきっと今以上に大変になることでしょう。
その結果、数学嫌いな人が、今以上に増えることになるのは容易に想像できますが(苦笑)。
このように、物事をイメージ化する能力というのは、情報をスムーズに記憶したり読み取ったりするときに大きな役目を果たします。
さらに、イメージ化した情報が鮮明であればあるほど、それらを応用する力は高くなります。
なぜなら、鮮明なイメージを得るためには、反復して記憶する作業が不可欠だからですね。
すぐ頭の中にイメージできるぐらいになるまで、何回も学習していくわけです。
そして鮮明なイメージを得たあなたは、今までとは違い、ほかのことを考える余裕が生まれているはずです。
ほかのこととはあなたが得たイメージを、別のイメージと組み合わせたり再構築したりといったことですね。
これらがスムーズに頭の中で行われると、あなたのプログラミング能力は向上します。
なぜなら、解決したい物事の仕組みをイメージ化したものに対して、プログラミングのイメージを照らし合わせることができれば、プログラム設計の足がかりになるからですね。
では具体的に、プログラミング技術上達のためにはどんなイメージを持つようにすればよいのかについてですが…。
いつものことながら紙面がなくなってきましたので、続きは次回お話ししたいと思います。
それでは今回の学習に移りましょう。
今回は、 配列変数 をいろいろな形で操作するということを学習していきましょう。
配列については以前学習しましたよね。
忘れてしまった場合は、しっかり読み返して復習しておいてください。
配列とはちょうど、番号を付けられた変数が一列にずらっと並んでいる状態をイメージしていただければわかりやすいかと思います。
配列を使うと一度にたくさんの変数を作成することができますから、データベースから受け取った値を格納するといった用途などに使います。
それでは、配列の各種操作方法について学習していきましょう。
配列先頭への操作
まずは Perl/CGIプログラム で、配列の先頭の要素に対して、削除や追加といった処理を行う方法をみていきましょう。
配列先頭の要素を削除
ここでは、配列変数の先頭の要素を削除する方法について解説していきます。
当然ですが、配列先頭の要素が削除された場合、それ以降の添え字はひとつずつくり上がります。
#!/usr/bin/perl
print "Content-type: text/html\n\n";
@number = ('zero', 'one', 'two', 'three', 'four');
shift @number;
for ($i=0;$i<=$#number;$i++) {
print "$i : $number[$i]<br>\n";
}
exit;
このPerl/CGIプログラムを実行すると、以下のように表示されます。
0 : one
1 : two
2 : three
3 : four
配列変数の先頭の要素が削除されていますよね。
配列先頭の要素を削除するには、shift関数を使います。
shiftとは、配列変数の先頭の要素を削除し、後の添え字をひとつずつくりあげる関数です。
英語でshiftは、「何かをどこかへ移動させてテキパキ切り替える」といったニュアンスで使われます。
例えば、従業員の勤務時間を調節した表のことをシフトと言ったりしますよね。
あれは、従業員全体で問題なく回っていくように、各従業員の労働時間を切り替えていることからshiftと言うのです。
もっと身近なところでは、パソコンのshiftキーがあります。
同じAキーでも、ただAキーを押したときと、shiftキーを押しながらAキーを押した時では、表示される文字が変わりますよね。
これは、shiftキーがAキーの動作を切り替えているからですね。
これと同じで、shift関数は配列先頭を切り取り、配列全体の要素を切り替えるという意味で使います。
さらに、shift関数の応用術として、削除した値を取り出すこともできます。
「shift @number;」部分を…
「$num = shift @number;」と書き換えると、変数「$num」には、配列先頭の値「zero」が入ります。
その後の forループ については改めて解説する必要ないですよね。
以前みっちり学習していますので、わからない場合は読み返してくださいね。
配列先頭に要素を追加
ここでは、配列の先頭に要素を追加する方法をみていきましょう。
配列の先頭に新しく要素が追加されると、それ以降の添え字はすべてひとつ後ろに下がります。
ようするに、先ほどとは逆の動きをするということです。
#!/usr/bin/perl
print "Content-type: text/html\n\n";
@number = ('zero', 'one', 'two', 'three', 'four');
unshift(@number, 'x');
for ($i=0;$i<=$#number;$i++) {
print "$i : $number[$i]<br>\n";
}
exit;
このPerl/CGIプログラムを実行すると、以下のようになります。
0 : x
1 : zero
2 : one
3 : two
4 : three
5 : four
配列の先頭に要素を追加したことにより、すべての添え字がひとつ後ろに下がりました。
このようなことを可能にしているのが、unshift関数です。
unshiftとは、配列の先頭に要素を追加する関数です。
先ほどとは逆ですね。
shift関数に、逆を表す「un」が付いていますから、動作も逆になるというわけです。
「un」を頭につけると、本来持っている意味とは逆の意味として扱われます。
わかりやすいところでは、「install(インストール)」という言葉があります。
「パソコンにソフトウェアをインストールする」というように使いますが、これは、パソコンに何らかのプログラムを組み込むことですよね。
そして、逆の意味つまり、パソコンから何らかのプログラムを取り除くことを「アンインストール」と言いますよね。
これは「install」という単語に、頭に「un」を付けて「uninstall」という逆の意味をもった単語を表現しています。
今回のunshift関数もこれと同じ感じで覚えておくと楽に覚えられると思います。
ちなみに、unshift関数を使わなくても、配列の先頭の要素を追加することはできます。
unshift関数を使わずに、上記のプログラムと同じことをさせるには…。
「unshift(@number, 'x');」この部分を…。
「@number = ('x', @number);」と書き換えればOKです。
これで配列先頭の要素に対する操作方法の解説は終了です。
<戻る>
配列末尾への操作
Perl/CGIプログラミングで、配列末尾の削除と追加方法について学習していきます。
配列末尾の要素を削除
ここでは、配列の一番最後の要素を削除する方法について解説します。
配列最後の要素ですから、とくに添え字がくり上がったりくり下がったりなどということは起こりません。
#!/usr/bin/perl
print "Content-type: text/html\n\n";
@number = ('zero', 'one', 'two', 'three', 'four');
pop @number;
for ($i=0;$i<=$#number;$i++) {
print "$i : $number[$i]<br>\n";
}
exit;
このPerl/CGIプログラムを実行すると、以下のように表示されます。
0 : zero
1 : one
2 : two
3 : three
配列の末尾を削除するには、pop関数を使います。
popは、おそらく何かの略語だとは思うのですがよくわからなかったので、もしご存知の方は教えてください。
そういうことですからとりあえずは機械的に、「pop関数は配列最後の要素を削除する」と覚えておいてください(苦笑)。
ここでは配列の最後の変数を削除するために、「pop @number;」としていますが…。
pop関数は、前述のshift関数と同じように、操作した値を取り出すこともできます。
pop関数で削除した値を取り出すには「pop @number;」この部分を…。
「$num = pop @number;」とします。
こうすると、変数「$num」に「four」が代入されます。
配列末尾に要素を追加
ここでは配列最後にもうひとつ要素を追加して、配列全体の要素数を増やす方法について学習していきましょう。
配列末尾に要素を追加することは、そんなに難しいことではないらしく、いくつかのやりかたがあります。
ここでは、大きく3種類の方法を学んでいきます。
念のために書いておきますが、どれを選んでプログラミングするかは好みの問題ですからね。
どれが良い悪いということではありません。
現在の要素数を利用する場合
まずは操作したい配列の要素数を調べて、そこにひとつ要素を追加する方法をみていきましょう。
#!/usr/bin/perl
print "Content-type: text/html\n\n";
@number = ('zero', 'one', 'two', 'three');
$number[$#number+1] = 'four';
for ($i=0;$i<=$#number;$i++) {
print "$i : $number[$i]<br>\n";
}
exit;
このPerl/CGIプログラムを実行すると、以下のように表示されます。
0 : zero
1 : one
2 : two
3 : three
4 : four
これは添え字を直接指定することにより、最初に定義された要素以外の要素を直接作り出す方法です。
ただしこの方法を使うためには、操作したい配列最後の添え字の数値がいくつであるかを知っておく必要があります。
なぜなら、誤ってすでに存在している添え字を指定した場合、その要素は上書きされてしまうからです。
逆に、配列最後の添え字の番号よりも離れていた場合、その隙間は未定義の要素で埋められることになりますから、その結果データ記憶領域の無駄使いになります。
配列最後の添え字の番号を調べるためには、配列名の頭に「$#」を付けます。
これは、以前学習済みですから、忘れてしまった場合は読み返して復習しておきましょう。
ということは、配列末尾に追加する添え字の番号を指定することは簡単ですね。
配列最後の添え字を参照する「$#配列名」に1たせばよいわけです。
「$number[$#number+1]」という部分がそうですね。
機械的に配列末尾の要素を追加する場合
次も同じように配列末尾に要素を追加するのですが、今度のは添え字を使わずに、今まで学習してきた知識を生かした方法で要素を追加します。
#!/usr/bin/perl
print "Content-type: text/html\n\n";
@number = ('zero', 'one', 'two', 'three');
@number = (@number, 'four');
for ($i=0;$i<=$#number;$i++) {
print "$i : $number[$i]<br>\n";
}
exit;
このPerl/CGIプログラムを実行すると、以下のように表示されます。
0 : zero
1 : one
2 : two
3 : three
4 : four
配列末尾に要素を追加しているのは、「@number = (@number, 'four');」という部分ですね。
カッコを使って配列すべての要素を再定義しています。
このやり方であれば、今まで学習してきた知識で解決しますよね。
先ほどのような「$#」を知らないとできないわけではないので、ハードルは低いんじゃないかと勝手に思っています(苦笑)。
関数を使う場合
最後に、配列末尾に要素を追加する関数を使う方法について解説します。
#!/usr/bin/perl
print "Content-type: text/html\n\n";
@number = ('zero', 'one', 'two', 'three');
push(@number, 'four');
for ($i=0;$i<=$#number;$i++) {
print "$i : $number[$i]<br>\n";
}
exit;
このPerl/CGIプログラムを実行すると、以下のように表示されます。
0 : zero
1 : one
2 : two
3 : three
4 : four
pushとは、配列の最後に要素を追加する関数です。
これが一番美しい感じがしますね(笑)。
pushは、日本語でもプッシュするといいますよね。
押し込むといったニュアンスで使います。
ですからpush関数は、配列の最後にぐいぐいっと、新しい要素を押し込んでいるようなイメージです。
配列指定要素への操作
Perl/CGIプログラミングで配列の指定した要素に対して、削除や追加操作をする方法をみていきましょう。
ここで学習します配列要素の削除や追加方法は、前述のような配列先頭または配列末尾限定への操作ではなく、配列の途中の要素に対しても操作が可能です。
配列の指定した要素に対して、削除や追加操作をするには、splice関数を使います。
splice関数は、添え字の番号を直接指定して操作しますから、どの位置にある要素でも操作できます。
配列指定要素の削除
まずはsplice関数を使って、配列の指定要素を削除してみます。
#!/usr/bin/perl
print "Content-type: text/html\n\n";
@number = ('zero', 'one', 'two', 'three', 'four');
splice (@number, 1, 2);
for ($i=0;$i<=$#number;$i++) {
print "$i : $number[$i]<br>\n";
}
exit;
このPerl/CGIプログラムを実行させると、以下のように表示されます。
0 : zero
1 : three
2 : four
splice関数を使って、配列の2つ目の要素と、3つ目の要素を削除しました。
Perl/CGIプログラム例では、「splice (@number, 1, 2);」という部分がそうですね。
splice関数の使用方法はいろいろありますが、ここでは、配列の添え字位置から、削除する要素の数を指定して削除しています。
具体的には、「splice (配列名, 開始位置, 開始位置からの要素の数)」という感じで使っています。
「splice (@number, 1, 2);」ですから…。
削除開始位置は、1が指定されていますから、添え字1が割り当てられている配列2番目の要素がこれにあたります。
開始位置からの要素の数は2が指定されているので、開始位置の要素を含めた2つの要素が指定されているということになります。
つまり、削除される2つの要素とは…。
1つ目は、開始位置である配列2番目の要素、値は「one」。
2つ目は、開始位置の次の要素、値は「two」。
ということになります。
さらに、splice関数も前述したshift関数や、pop関数と同じように、配列から削除した変数の値を取得することができます。
今回であれば「splice (@number, 1, 2);」の部分を…
「@num = splice (@number, 1, 2);」と書き換えます。
こうすると、配列「@num」には、splice関数で削除した配列変数の値が格納されます。
配列指定要素の追加
次はsplice関数を使って、配列の指定要素を追加してみます。
#!/usr/bin/perl
print "Content-type: text/html\n\n";
@number = ('zero', 'one', 'four');
@num = ('two', 'three');
splice (@number, 2, 0, @num);
for ($i=0;$i<=$#number;$i++) {
print "$i : $number[$i]<br>\n";
}
exit;
このPerl/CGIプログラムを実行すると、以下のように表示されます。
0 : zero
1 : one
2 : two
3 : three
4 : four
splice関数を使って、配列「@number」の最初に定義されていた3つの全要素数を、5つに追加しました。
具体的には配列「@number」の2番目の要素と3番目の要素の間に、新たに配列「@num」の2つの要素を追加しています。
その結果、配列「@number」のすべての要素の数は5つとなり、もともと3番目だった要素は5番目の要素にくり下がりました。
Perl/CGIプログラム例では「splice (@number, 2, 0, @num);」という部分がそうですね。
先ほどsplice関数の使い方で、「splice (配列名, 開始位置, 開始位置からの要素の数)」で指定した添え字の番号をもった要素を削除できることを解説しましたね。
今回はその応用で、「追加したい要素」という項目を新たに追加しています。
つまり、「splice (配列名, 開始位置, 開始位置からの要素の数, 追加したい要素)」という感じになっています。
配列名は「@number」です。
開始位置は「2」で、これは処理を開始する添え字の番号を表していますから、3番目の要素から処理を始めるといったことを表しています。
開始位置からの要素の数は「0」で、これは削除するべき要素が、ひとつもないことを表しています。
追加したい要素は「@num」に格納されている要素ですね。
splice関数を使った配列要素の追加方法については以上です。
これで配列の指定した要素に対して、削除や追加といった処理を自由に作成できるようになりましたね。
配列指定要素の置換
最後に、splice関数を使って配列の要素を、別の配列の要素に置換するという方法について学習していきましょう。
この方法を使うと、ある配列の一部に対して、別の配列の要素を挿入することができます。
文章であれこれ説明してもわかりにくいと思うので、まずは、以下のPerl/CGIプログラムを見てください。
#!/usr/bin/perl
print "Content-type: text/html\n\n";
@number = ('zero', 'one', 'two', 'three', 'four');
@num = (1, 2);
splice (@number, 1, 2, @num);
for ($i=0;$i<=$#number;$i++) {
print "$i : $number[$i]<br>\n";
}
exit;
このPerl/CGIプログラムを実行させると、以下のように表示されます。
0 : zero
1 : 1
2 : 2
3 : three
4 : four
配列「@number」の要素の一部が、別の配列「@num」の要素に置き換わっています。
前述の配列指定要素の追加と同じように、splice関数を使って、指定配列の要素に対して追加処理をかけています。
ただし今回は、削除する要素の数を指定しているので、削除処理と挿入処理が同時に行われている感じです。
削除する要素の数と、新たに挿入する要素の数が同じなため、配列要素が置換されたように見えています。
splice関数の使い方としては前述のやり方と同じですが、使い方によっては、このように置換処理をかけているように見せかけることができるというわけです。
使い方がいろいろあるので少し複雑に感じますが、便利な関数なので使いこなせるようにしておきましょう。
英語でspliceとは、同じ種類のような何かと何かをつなぎ合わせるといった意味で使われます。
ですから、splice関数は、一度切断した配列要素をつなぎ合わせたり、別の配列要素同士をつなぎ合わせるときにつかうものだとイメージしておくと覚えやすいと思います。
これで今回の学習テーマである、配列操作プログラミングについての学習は以上です。
配列はとても便利な変数ですから、その使い方はぜひ覚えておきましょう。
編集後記
今回の編集後記は、積み上げ型の学習について書きます。
現実に積み上げ型の学習という定義が存在するかどうかは知りませんが、ここでは便宜上この名前を使っていきますね。
積み上げ型の学習とは、基本的なところから始めて徐々に関連知識を広げてゆき、最後はそれらを応用していくといったタイプの学問のことです。
ほぼすべての学問がこの知識を積み上げていくタイプに属します。
英語や数学などをイメージしていただければわかりやすいと思います。
英語であればアルファベットから始まり、単語や活用などを覚え、最後には英語を理解するという目的を達成していきます。
数学であれば、数字やその関係からはじまり、計算方法を覚え、最終的には理論的に考えていく力を身につけていくわけです。
で、何を言いたいのかというと…。
今あなたが学習しているPerl/CGIプログラミングも立派な積み上げ型の学習ですよと言いたいのです。
Perl/CGIプログラミングであれば、基本的な関数の使い方から始まり、その種類や応用方法を学んでゆき、最終的にはPerl/CGIプログラムが理解できるようになるわけです。
そしてここからが本題なのですが、このような積み上げ型の学習の場合、大切な部分というのはほとんどが基本的なところにあるということを覚えておいてください。
なぜならまず基本的な考え方というのがあって、後から学習していく部分というのは、いかに基本を応用していく考え方ができるかというところにかかってくるからですね。
あなたも学生時代に勉強してきた英語や数学を思い浮かべていただければ、わかっていただけるかと思います。
中学レベルの英語や数学をすっとばして、いきなり高校レベルの英語や数学の問題は解けませんよね。
中学時代は遊んでいて、高校からいきなり英語や数学をがんばろうとしても、基本的な積み上げがないわけですからさっぱりわからないわけです。
その場合はやはり、一度中学レベルに戻って、すごい勢いで基本的な部分から積み上げていくしかありません。
Perl/CGIプログラミング学習もこれと同じで、関数の種類やその活用方法などといった基本的なことが理解できていなければ、たとえ小さなプログラムでも理解できません。
とはいってもプログラムという性質上、実際に動かした結果から考察してみることは可能ですから、ある意味敗者復活戦があるわけですよね。
今回であれば、配列操作を行った後に、forループを使ってすべての要素を出力させている部分がありましたよね。
forループに関しては、以前こってり解説していましたから、今回改めて解説することはしませんでした。
でも、Perl/CGIプログラミング学習をしようと思って、今回初めてこのページを読んだ人もいるわけですよ。
その人にとっては、for関数の使い方なんて知らないわけです。
しかし、実行結果も一緒に書いていますから、そこから考えて「こんな風に書くと、配列の要素の数だけ処理を繰り返すんだな」ということが予想できるわけです。
本当にPerl/CGIプログラミング初心者で、今回初めてこのページを読んだ人がいるかもしれません。
そんなあなたは、正解不正解は別として、そのぐらいは頑張ってみてくださいね。
↑まるなげかよっていう声が聞こえてきそうですが(苦笑)。
で、最終的には何が言いたいのかというと、きっと、今後もこのようなことが起こってくると思うんですよ。
どういうことかというと、今回であれば、はじめて登場しました配列操作関数の解説を強調するために、以前に出てきた部分は省略するといったことです。
その場合どうしても一定の割合で、解説している内容が理解できないという人が出てきます。
この連載は、一回分の学習内容が多いですから、特にその傾向が出てくるかと思います。
もしあなたがそうなってしまったら、Perl/CGIプログラミング学習がつまらないものになってしまいますよね。
スパルタ的な方針で、「わからないことは自分で調べろ」とか…。
「わからない人は無視しておいていく」といったこともやろうと思えばできますが…。
そうしてしまうと、せっかくこの記事を書いてこうしてあなたにお届けしている意味がなくなってしまいます。
あなたもきっと読者を無視したようなページは、読みたくないし読む意味もないと思うはずです。
ですから、解決策として…。
「今の段階ではまだ基本的な部分を学習している最中なので、1回1回しっかりPerl/CGIプログラミング学習をこなしていってください」ということを、声を大にして言いたいです。
今からであればまだ最初からやり始めても、学習量は少なくてすみます。
もちろんこれは、基本的なことを学習している今の段階だからこそ言えることです。
この連載が回数を重ねていくにつれて、徐々にハードルが高くなっていき、最後には通用しなくなることは分かっています。
そのときはそのときで、別の手段を考えていますから、とりあえず今の段階では、各ページに書かれていることを確実にこなしていってください。
回りくどく書いたので長くなってしまいましたが、せっかくこのページにめぐり合ったわけですから、一緒にがんばっていきましょう!
ありがとうございました。
<戻る>