配列の重複要素をカウントし、まとめる #perl #shell
首題の通り、配列の重複要素をカウントして、まとめていくコードをperlで書きました。
SHELLで言うuniqコマンドのcオプション「#uniq -c」と同じ機能です。
ロジックは難しくないのですが、初期化エラーではまったのでメモ。
サンプルコードは以下の通り。
サンプルコード(disinct.pl)
#!/usr/bin/perl use strict; use warnings; my @LINE=("東京都","神奈川県","千葉県","神奈川県","東京都","埼玉県"); my %cnt; #同じキーがあれば、値が1ずつ増加していく foreach my $key (@LINE){ if ($cnt{$key}) { $cnt{$key}=$cnt{$key}+1; } else { $cnt{$key}=1; } } #カウントした回数(値)をキーとともに出力 foreach my $key (sort(keys(%cnt))){ print "$cnt{$key} $key\n"; }
結果
$perl disinct.pl 1 千葉県 1 埼玉県 2 東京都 2 神奈川県 $
処理
1. 配列、ハッシュを宣言
2. 配列要素を$keyに入れながらforeachでループさせる
3. $keyをハッシュのキーとして、if文で同じキーがあるかチェックし、ハッシュ値を増加(カウント)させる
4. 最後にハッシュ値(カウント数)をキーとともに出力させる
といったロジックになってます。
で、3.のforeach文の中でif文を用いてキーをチェックしているのが今回勉強になった点でして、例えば次のように書くと...
foreach my $key (@LINE){ $cnt{$key}=$cnt{$key}+1; }
「Use of uninitialized value within %cnt in addition (+) at disinct.pl line 12」
とwarningが出力されてしまいます。これはwaringsプラグマを付けているために出力され、「初期化されてない変数に+してるよ!」って言われています。
本当に初期化されていないかを当該の前で変数の中身をData::Dumperで見てみます。
$perl disinct.pl $VAR1 = undef; Use of uninitialized value within %cnt in addition (+) at disinct.pl line 13. $VAR1 = undef; Use of uninitialized value within %cnt in addition (+) at disinct.pl line 13. $VAR1 = undef; Use of uninitialized value within %cnt in addition (+) at disinct.pl line 13. $VAR1 = '1'; $VAR1 = '1'; $VAR1 = undef; Use of uninitialized value within %cnt in addition (+) at disinct.pl line 13. (省略)
確かに"undef"(未定義値)。つまり初期化されていないわけです。
もちろん、上記のコードでも想定の結果を得られるので、warningプラグマを外してしまえば怒られませんし、コードがすっきりするためそれはそれで良いと思います。が、warningsプラグマをはずすのは後々のメンテナスが大変になりますし、他のエラーを発見しにくくになってしまいます。きちんと回避コードを書いておくべきかと思います。
おわり。