--- title: '『新版Perl言語プログラミングレッスン入門編』第6章: 繰り返し' author: kazu634 date: 2008-02-06 url: /2008/02/06/_839/ wordtwit_post_info: - 'O:8:"stdClass":13:{s:6:"manual";b:0;s:11:"tweet_times";i:1;s:5:"delay";i:0;s:7:"enabled";i:1;s:10:"separation";s:2:"60";s:7:"version";s:3:"3.7";s:14:"tweet_template";b:0;s:6:"status";i:2;s:6:"result";a:0:{}s:13:"tweet_counter";i:2;s:13:"tweet_log_ids";a:1:{i:0;i:3691;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}' categories: - Perl - Programming ---

 繰り返しについて勉強するよー

foreach構文

 これまで何度も出てきた構文。変数の中にリストの値を順番に格納する構文だよ。基本構造は

foreach my 変数 (リスト) {
処理
}

というようになる。「my 変数」は省略可能で、処理の中で「$_」と表記できる。例はこんな感じ:

use strict;
use warnings;
my @name = ('Musashi', 'Aiko', 'Nanbu');
foreach (@name) {
print "$_\n";
}

リストの値でソートさせて表示させたいときにはこのようにする。

use strict;
use warnings;
my @name = ('Musashi', 'Aiko', 'Nanbu');
foreach (sort(@name)) {
print "$_\n";
}

逆順にソートするときは「reverse(sort(@name))」とすればいい。reverseは「リストの内容を単純に逆にするだけ」ということに注意。だから「reverse(@name)」は

  1. Nanbu
  2. Aiko
  3. Musashi

という結果になるよ!当たり前だけど、foreachを二重(orそれ以上)にすることもできる。例としてはこんなのが載っていた:

use strict;
use warnings;
my @data = (
"Musashi, 70, 83, 41",
"Aiko, 90, 70, 50",
"Nanbu,100, 30, 20",
);
foreach (@data) {
my ($name, @score) = split(/,/, $_);
my $sum = ;
foreach (@score) {
$sum += $_;
}
print "$name: $sum\n";
}

自分としては「my ($name, @score) = split(/,/, $_);」がファジーすぎると感じる。説明によれば、

split(/,/, $line)は、$lineの文字列をコンマで区切り、そのそれぞれの要素をまとめたリストを作ります。例えば、$lineの値が

'Hiroshi Yuki, 70, 83, 41'

だとすると、split(/,/, $line)の値は、

('Hiroshi Yuki', '70', '83', '41')

というリストになります。代入する先の左辺は、($name, @score)というリストになっているので、

my $name = 'Hiroshi Yuki';
my @score = ('70', '83', '41');

と同じことになります。

「同じことになる」で済ませられているけど、なんかかなりファジーな気がするんですが。。。でも、直感的と言えば直感的かもしれない。要は「最初のヤツだけ$nameに格納、後は@scoreにまとめちゃって」ということなんだろう。

 foreach構文の使い道は他にもあって、「ファイルの各行を読み込む」時にも使うよ。例はこんな感じになる。

use strict;
use warnings;
open (FILE, 'file.txt') or die "$!";
foreach (<FILE>) {
print $_;
}
close (FILE);

説明にはこんな事書いてあったよ!

「リスト」のところにはと書いてあります。Perlではリストを書くべきところにと書くと、FILEというファイルハンドルからすべての行をメモリ上に読み込み、その各行を要素とするリストを作成します。これはPerlの約束です。

 他にも「ディレクトリ内部の各ファイルの繰り返し」にも使えるよ!

use strict;
use warnings;
opendir (DIR, '.') or die "$!";
foreach (readdir(DIR)) {
print "$_\n";
}
closedir (DIR);

 この前の章でもやったけど、「keysを使うとハッシュを表示できる」よ♪

use strict;
use warnings;
my %hash = (
'Kazu' => 10,
'Yukari' => 20,
'Aiko' => 30,
'Nanbu' => 40,
);
foreach (keys(%hash)) {
print "$_: $hash{$_}\n";
}

「keys(%hash)」で「(‘Kazu’, ‘Yukari’, ‘Aiko’, ‘Nanbu’)」というリストが得られるよ!なにげに「”$_: $hash{$_}\n”;」を「”$_: %hash{$_}\n”」としてしまい、ややはまる。抜けているなー。

whileを使った繰り返し

 whileの処理はこんな感じになっている:

while (条件式) {
繰り返す処理
}

条件式が満たされている間中はずっと繰り返し処理を行う。例はこんな感じ。

use strict;
use warnings;
open (FILE, 'temp.txt') or die "$!"
while (my $line = <FILE>) {
print $line;
}
close(FILE);

これを別な書き方にもできる。

use strict;
use warnings;
open (FILE, 'temp.txt') or die "$!"
while (<FILE>) {
print $_;
}
close(FILE);

この「$_」の使い方も少し不思議だけど、説明によると:

whileの中でを使うと、読んだ行の内容がデフォルト変数$_に代入されます。

というわけで、お約束らしい。