masatoの日記

やっていきます

Perlで2次元ハッシュをつくる

ハッシュの中にハッシュを入れて2次元データ構造をつくってみる。

今回はハッシュのハッシュレファレンスにしてみた。

「すぐわかる Perlオブジェクト指向」(123ページ)

サンプルコード

use strict;
use warnings;
use DDP;

my $hash_ref_with_hash;
my $category;

while  (<DATA>) {
    chomp;
    if ( /^\[(.*)\]/ ) {
        $category = $1;
    } elsif (/^(.*)=(.*)$/) {
        $hash_ref_with_hash->{$category}{$1} = $2;
    }
}

p $hash_ref_with_hash;

__DATA__
[File]
perl_root=C:\Perl
tmp=C:\tmp
file1=file1.txt
file2=file2.txt
file3=file3.txt
[Internet]
web=http://www.gihyo.co.jp/
ftp=ftp://www.gihyo.co.jp/

出力

p $hash_refの出力。

\ {
    File       {
        file1       "file1.txt",
        file2       "file2.txt",
        file3       "file3.txt",
        perl_root   "C:\Perl",
        tmp         "C:\tmp"
    },
    Internet   {
        ftp   "ftp://www.gihyo.co.jp/",
        web   "http://www.gihyo.co.jp/"
    }
}

つまずきポイント

1.ハッシュレフにハッシュを入れる方法は、$hash_ref->{key} = $valueとする。 $hash_ref->{ $key => $value}とすることはできない。

2.キャプチャ箇所の取得方法 if ($line = /^\[(.*)\]/) { $captcha = $1 }とすると簡潔になる。

それ以前はいったん置換してから、その結果を新しい変数に代入するという冗長なことをやっていた。

こんな風に。

if ($line =~ /^\[/) {
    $line = s/^\[(.*)\]/$1/;
    $captcha = $1;
}

展開する方法

keys %{$hash_ref_with_hash->{$category}}の部分がポイント。

見た目が仰々しい。

## プレーンハッシュのハッシュレファレンスを展開する
for $category (keys %$hash_ref_with_hash) {
    for my $key (keys %{$hash_ref_with_hash->{$category}}) {
        print "[$category]\n";
        print "    $key    $hash_ref_with_hash->{$category}{$key}\n";
    }
}