16章(単純なデータベース) 練習問題1

perlfunc.podファイルを読んで、その中から=item行に書かれている識別氏名を探し出すプログラムを書いてください。このプログラムは、各識別子が登場する最初の行番号を記録したデータベースを作成します

はいはい、やってみました。

#!/usr/bin/perl
use strict;
use warnings;

dbmopen(my %DATA, "perlfunc", 0644) or die "cannot create perlfunc: ($!)";

while(<>) {
    if ( (/^=item\s+([a-zA-Z]\w*)$/) and (! exists $DATA{$1}) ) {
	$DATA{$1} = $.;
    }
}

ちょっとしたテストケースも作成しました。

=item hoge
=item hoge
=item fuga
=item piyo
=item a
=item b
=item c
=item a
=item c
=item c

このテストケースを前述のプログラムで実行し、次のテストプログラムに通すと…

#!/usr/bin/perl
use strict;
use warnings;

dbmopen(my %DATA, "perlfunc", 0644) or die "cannot open perlfunc: ($!)";
while (my ($key, $value) = each %DATA) {
    print "$value -> $key\n";
}

以下の結果が出力されます。

1 -> hoge
3 -> fuga
4 -> piyo
5 -> a
6 -> b
7 -> c

ちゃんと各識別子が登場する最初の行番号を記録していますね。


それでは解答をチェック。
ふむ。大体同じ。
ですが今まで見たことの無いテクニックがありました。
それを用いてこの練習問題のプログラムを改良するとこんなのになります。

#!/usr/bin/perl
use strict;
use warnings;

dbmopen(my %DATA, "perlfunc", 0644) or die "cannot create perlfunc: ($!)";

while(<>) {
    if ( (/^=item\s+([a-zA-Z]\w*)$/) ) {
	$DATA{$1} = $DATA{$1} || $.;
    }
}

重要な改良箇所は

$DATA{$1} = $DATA{$1} || $.;

ここ。
このテクニックは覚えておいて損はなさそう。