Perlのハッシュの作成と参照入門
構文
引用」を作成する方法と、それを使用する方法は2つだけです。
リファレンスを作成する
ルール1の作成
変数の前に「/」記号を付けると、その変数への「参照」が得られます。
$aref = /@array; # $arefは@arrayへの「参照」を保持します。
$href = /%hash; # $href は %hash への「参照」を保持します。
arefや$hrefのような変数に「参照」を保存すると、他のスカラーと同じようにコピーや保存ができるようになります。
xy = $aref; # $xy は @array への「参照」を保持します。
p[3] = $href; # $p[3] は %hash への '参照' を保持するようになりました。
$z = $p[3]; # $z は %hash への '参照' を保持します。
これらの例では、名前の付いた変数への「参照」を作成する方法を示しましたが、時には名前のない配列やハッシュを作成することもあります。これは、変数に入れない文字列 '/n' や数字 '80' を使うときと似ています。
作成ルール2
[ITEMS ] は新しい無名配列を作成し、その配列への '参照' を返します。{ITEMS } は、新しい無名ハッシュを作成し、そのハッシュへの「参照」を返します。
$aref = [ 1, "foo", undef, 13 ]。
# $aref はこの配列への「参照」を保持します。
$href = { APR =>; 4, AUG =>; 8 }.
# $href はこのハッシュへの「参照」を保持します。
ルール2からの「参照」とルール1からの「参照」は、同じ型である。
# ここで
$aref = [ 1, 2, 3 ]。
# 上と同じです。
@array = (1, 2, 3)です。
$aref = /@array;
最初のメソッドは、余分な配列変数 @array を作成しないことを除いて、次の2行を省略したものです。
記号[]を書くだけなら、新しい空の無名配列が得られます。記号 {} を使用すると、新しい、空の匿名ハッシュが得られます。
リファレンスを使用する
参照」を作成すると、その参照で何ができるのでしょうか?それはスカラーであり、他のスカラーと同じように保存したり取り出したりすることができます。それ以外に、2つの使い方がある。
使用ルール1
配列の名前を中括弧で囲んだ配列の'参照'に置き換えることはいつでもできます。例えば、@arrayの代わりに@{$aref}を使用します。
以下は使用例です。
配列です。
a @{$aref} 配列です。
reverse @a reverse @{$aref} 配列を逆順に並べ替え
$a[3] ${$aref}[3] 配列のメンバ
$a[3] = 17; ${$aref}[3] = 17 メンバーに値を代入する
上の各行で、2つの式は同じ関数を実装しています。左側の式は配列 @a を操作し、右側の式は「参照」 $aref が指す配列を操作します。これらは、配列に対して同じ効果をもたらします。
ハッシュの「参照」を使うことは、配列の「参照」を使うことと全く同じです。
h %{$href} A ハッシュ
keys %h keys %{$href} キーを取り出すハッシュです。
$h{'red'} ${$href}{'red'} ハッシュのメンバーです。
$h{'red'} = 17 ${$href}{'red'} = 17 メンバーに値を代入する
参照」を使って何をしたいのか、その方法は使用規則1がすでに教えてくれています。普通の配列やハッシュのようにPerlのコードを書いて、配列やハッシュの名前を{$reference}に置き換えるだけです。'参照'が1つしかないときに配列全体をたどるにはどうしたらいいか?' こんな風に書くんだ。
for my $element (@array) {...
...
}
そして、配列名@arrayを'reference'に置き換えてください。
for my $element (@{$aref}) {.
...
}
'参照'しかないのにハッシュの中身を表示するには?' まず、ハッシュ全体を表示するコードを書いてください。
for my $key (キー %hash) { (キー %hash)
print "$key =>; $hash{$key}/n";
}
そして、そのハッシュの名前を'quote'で置き換えてください。
for my $key (キー %{$href}) {...
print "$key =>; ${$href}{$key}/n";
}
使用ルール2
ルール1を使うことは、本当に必要なことです。なぜなら、それは「参照」をどのように処理するかを示しており、ほとんどすべての「参照」に対して機能するからです。しかし、私たちが通常行うのは、配列やハッシュの1つのメンバーだけを扱うことであり、ルール1を使うのは不便な方法なので、簡単にできる方法があります。
${$aref}[3]は読みにくいので、$aref->[3]のように記述します。
${$href}{red}と書くと扱いにくいので、$href->{red}のように書きます。
もし$arefが配列への「参照」を保持しているならば、$aref->[3]はその配列の4番目のメンバーです。全く別の配列の4番目のメンバーを表す$aref[3]と混同しないように、紛らわしい配列は@arefとします。変数$arefと@arefは、$itemと@itemと同じように、全く無関係です。
同様に、$href->{'red'}は名前のないハッシュであるにもかかわらず、ハッシュによって「参照」される変数$hrefの一部となっています。そして、$href{'red'}は、別の紛らわしい名前のハッシュである%hrefの一部となっています。記号 ' ->' を書くのを忘れがちで、そうなるとプログラムがデータを取り出したくない配列やハッシュからメンバーを取り出したときに、変な計算結果になってしまうのです。
例
例を見てみましょう。
まず、[1, 2, 3] は (1, 2, 3) を含む無名配列を作成し、その配列への「参照」を返すことを覚えておいてください。
では、考えてみましょう。
@a = ( [1, 2, 3],
[4, 5, 6],
[7, 8, 9]
);
aは3つのメンバーを持つ配列で、それぞれが別の配列への「参照」となっています。
a[1]はこれらの「参照」の1つです。これは (4, 5, 6) を含む配列を指しており、これは配列への「参照」なので、ルール 2 を使用すると、この配列の 3 番目のメンバーを取得するには $a[1]->[2] のように記述するように指示されます。 同様に、$a[0]->[1]の値は2です。ここでは2次元配列を使っていますが、$a[ROW]->[COLUMN]を使えば、配列の任意の行の任意の列のメンバーを取得または設定することが可能です。
これらの記号はまだ少し面倒に思えるので、もっと簡単な使い方があります。
矢印記号のルール
2つの添え字の間の矢印は任意である。
a[1]->[2]の代わりに$a[1][2]と書いても同じである。a[0]->[1] = 23に対して、$a[0][1] = 23とこのように書きます;これらも同じことです。
これで本当に2次元配列に見えるようになりましたね。
なぜ矢印が重要なのか、おわかりいただけると思います。矢印がなければ、$a[1][2]の代わりに${$a[1]}[2]と書かなければならないのです。3次元配列の場合は、読みにくい${${$x[2]}[3]}[5]の代わりに、$x[2][3][5]と簡単に書けるようになるんだ。
解決方法
ここで、先に提示した問題の解決策として、都市名と国名を再フォーマットすることについて説明します。
my %table;
while (<>) {
chomp;
my ($city, $country) = split /, /;
$table{$country} = [] unless exists $table{$country};
push @{$table{$country}}, $city;
}
foreach $country (sort keys %table) {
print "$country: ";
my @cities = @{$table{$country}};
print join ', ', sort @cities;
print ". /n";
}
このプログラムは2つのパートに分かれています。2行目--7行目でデータの入力とデータ構造の作成が完了します。8行目から13行目までは、このデータを解析してレポートを出力する。ハッシュ %table を設定し、そのキーは国名で、堅牢な値はこの国名に対応する都市名の配列への「参照」である。このデータ構造は次のようなものである。
テーブル
+-------+--+
| |+-----------+--------+
ドイツ| *---->|フランクフルト|ベルリン| |。
| | +-----------+--------+
+-------+--+
| |+----------+
|フィンランド| *---->|ヘルシンキ| [詳細
| |+----------+
+-------+--+
| |+---------+------------+----------+
| アメリカ| *---->|シカゴ|ワシントン|ニューヨーク|...
| | +---------+------------+----------+
+-------+--+
まず、出力の部分から分析しましょう。構造はすでにできているとして、アウトプットはどのようにすればいいのでしょうか?
foreach $country (sort keys %table) {
print "$country: ";
my @cities = @{$table{$country}};
print join ', ', sort @cities;
print ". /n";
}
tableは通常のハッシュで、ここからキーの列を取得し、キーをソートし、すべてのキーに対して反復処理を行うことができます。ここで使われている「参照」は10行目だけです。 $table{$country}は、ハッシュのキー$countryを調べてその値を取得しています。このキーの値は、対応する国の都市の配列への「参照」である。利用規則1によれば、@{$table{$country}}を使えば、配列全体を復元することができるのです。10行目は次のようになります。
cities = @array。
違いは、ここでは配列の名前が「参照」{$table{$country}}に置き換えられていることです。シンボル@はPerlに配列全体を取得するように指示しています。都市のリストが得られたら、いつものようにソートして、都市名を結合し、プリントアウトします。
2〜7行目は、以下のようにデータ構造の作成を担当しています。
while (<>) {
chomp;
my ($city, $country) = split /, /;
$table{$country} = [] unless exists $table{$country};
push @{$table{$country}}, $city;
}
2~4行目では都市名と国名を取得します。そうでない場合、プログラムはシンボル[]を使って新しい空の匿名配列を作成し(作成規則2)、匿名配列への「参照」をハッシュの健全な値として置きます。
6行目では、都市名を対応する配列に入れます。table{$country}は、対応する国の都市の配列への「参照」を保持するようになりました。6行目は次のようになります。
push @array, $city;
違いは、ここでは配列の名前を{$table{$country}}に置き換えている点です。pushコマンドは、この「参照」が指す配列の末尾に都市名を追加します。
ここで一点、見落としていたことがあります。5行目は不要です。取り除けばいいのです。
while (<>) {
chomp;
my ($city, $country) = split /, /;
#### $table{$country} = [] unless exists $table{$country};
push @{$table{$country}}, $city;
}
もし、ハッシュ %table にこの国名 $country のレコードがすでにあれば、5行目を追加してもしなくても変わりはない。6行目は、「参照」である$table{$country}が指す配列に自分自身を位置付け、値$cityを配列に入れる。しかし、ギリシャのように%tableにそのキーが存在しない場合はどうするのでしょうか?
これはPerlで、それだけで仕事をきっちりこなしてくれます。存在しない配列にアテネを代入したいので、Perlは新しい空の無名配列を作り、それをハッシュ%tableに入れ、その配列にアテネという値を入れるのを助けてくれる。これは「自動生成」と呼ばれるもので、物事が自分で生成されるようにすることです。Perlはキーがハッシュにないことを発見し、自動的に新しいハッシュ・レコードを作成します。Perlはハッシュの健全な値として配列を使いたいことを知ると、自動的に無名の空の配列を作り、その配列への「参照」をそのハッシュに入れる。一般にPerlは、この新しい都市名を保持するために、メンバーサイズが1つのみの配列を作成する。
その他のセット
10%の詳細で90%の利益を得ることを約束しました。つまり、90%の詳細な知識を省略したのです。今、その重要な部分を見てください。これは、100%の詳細について述べているマニュアルthe perlref manpageを読むよりずっと簡単です。
マニュアルperlrefのmanpageからいくつかのハイライトを紹介します。
スカラー、関数など、あらゆるものへの「参照」を作成することができます。
使用法ルール1では、$arefのようなスカラー変数の中にある場合は、中括弧を省略することができます。例えば、@$arefは@{$aref}と同じであり、$$aref[1]は${$aref}[1]と同じである。初心者の方は、中括弧をつける習慣をつけるとよいでしょう。
以下の操作では、「参照」が指す配列はコピーされません。
$aref2 = $aref1;
同じ配列を指す2つの「参照」を得ることができます。もし $aref1->[23] の値を変更すれば、変数 $aref2->[23] を見たとき、それに応じて変更されます。
この配列をコピーするには、次のようにします。
$aref2 = [@{$aref1}];
記号 [...] を使って新しい無名配列を作成し、この新しい配列への「参照」を $aref2 に代入します。この新しい配列は、'参照' $aref1 が指す配列の内容で初期化されます。
同様に、匿名ハッシュをコピーするには、次のようにします。
$href2 = {%{$href1}} です。
変数が「参照」されている内容を保持しているかどうかを判断するには、関数 ref を使用します。その引数が「参照」である場合、返される値は「真」です。この関数は、実際にはよりよい仕事をします。ハッシュへの参照であれば「HASH」、配列への参照であれば「ARRAY」を返します。
参照」を文字列のように使いたい場合は、次のような文字列が得られます。
ARRAY(0x80f5dec)またはHASH(0x826afc0)
このような文字列が表示された場合、間違って「引用符」を出力していることを知る必要があります。
もうひとつ、この表示ではeqを使って2つの「参照」を比較し、同じものを指しているかどうかを確認することができます。(通常は == を使って比較することができます。)
文字列は「参照」と同じように使うことができます。配列への「参照」として "foo" を使用すると、配列 @foo への参照となります。これを「ソフトリファレンス」または「シンボリックリファレンス」と呼びます。これを無効にするには、use strict 'refs' という宣言を使います。誤って使ってしまうと、さまざまなエラーが発生する可能性があります。
perlrefのマニュアルよりもperllolのマニュアルページを見たほうがいいかもしれません。これはデータ構造のクックブックで、ハッシュ化された配列、配列のハッシュ、その他のデータ構造を扱うメソッドを提供しています。
関連
-
Django フレームワークでテンプレートフィルタをカスタマイズする
-
Perlの配列ソート学習ノート
-
Perl の読み書きファイルの簡単な例
-
python urllibでのエンコード処理例
-
Perlファイルの読み書きの学習ノート
-
PerlによるMSSQLへのアクセスとMySQLデータベースへの移行スクリプト例
-
perl で書かれた乱数話法プログラム (rand random function)
-
Perlのファイルハンドルの説明
-
perl変数$/の使用方法について説明します。コンテキストが行モードのとき、$/は行を区別するものを定義します。
-
問題発生 ----DBI ODBCエラー Perlスクリプトを実行中、エラー:[unixODBC][Driver Manager] データソース名が見つからない、およびデフォルトがない
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Perl6 のガベージコレクション
-
EditPlusでPerlの開発コンパイル環境を設定する
-
Perlは先頭と末尾の空白を削除します(左右の空白文字、空白文字を削除します)。
-
Perlでよく使われる記号と操作
-
Perl イテレーションディレクトリの例
-
perlを使ってデータテーブル(mysql)を分割し、データインスタンスを移行する。
-
dig と nali を使って DNS 解決アドレスが一貫しているかどうかを判断する Perl スクリプトです。
-
Perl コマンドライン引数内蔵配列 @ARGV
-
perlのファイルテスト演算子のまとめ
-
[解決済み] Perlで複数行のコメントを入力するにはどうしたらいいですか?[重複している]。