Y's note

Web技術・プロダクトマネジメント・そして経営について

本ブログの更新を停止しており、今後は下記Noteに記載していきます。
https://note.com/yutakikuchi/

Perlの多次元連想配列をJSONエンコードする方法

初めてのPerl 第5版

初めてのPerl 第5版

はじめに

業務でPerlを使う事になったので少しずつ学習した事を書いて行きます。この記事での目的は連想配列を多次元で定義して、その配列をjson_encodeします。
超簡単 Perl一問一答学習帳 - Yuta.Kikuchiの日記 はてなブックマーク - 超簡単 Perl一問一答学習帳 - Yuta.Kikuchiの日記

配列

定義

配列の定義には@を使います。@は配列を示す宣言ですが、定義の仕方は色々とあります。以下では()括弧、添字、qw演算子での指定について書きます。qw演算子とは空白での区切りでlistにしてくれるものです。

#!/usr/local/bin/perl -w

use strict;
use warnings;

# @を使う
my @sample = ( 'a', 'b', 'c' );

# $を使う
my @sample2;
$sample2[0] = 'a';
$sample2[1] = 'b';
$sample2[2] = 'c';

# qwを使う
my @sample3 = qw/a b c/;
取得

各要素を取得するにはfor,foreach,whileなどの繰り返し文が使えます。Perlの特徴的な記述とし$#配列名とすると配列の最後の添字番号を取得する事が出来ます。またforeachで括弧に@配列を入れると自動的に$_に要素を展開してくれます。スゴい事にPerlは繰り返しを使わなくても全要素を表示する事ができます。print @配列名またはprint "@配列名"とします。ダブルクォーテーションで配列名をくくるとスペース区切りで表示します。

#!/usr/local/bin/perl -w

use strict;
use warnings;

# @を使う
my @sample = ( 'a', 'b', 'c' );

# $を使う
my @sample2;
$sample2[0] = 'a';
$sample2[1] = 'b';
$sample2[2] = 'c';

# qwを使う
my @sample3 = qw/a b c/;

# forを使う $#で最後の添字番号取得
for( my $i=0; $i<=$#sample; $i++ ) {
  print $sample[$i];
}

print "\n";

# foreachで $_を使う
foreach( @sample ) {
  print $_ ;
}

print "\n";

# foreachで変数に展開
foreach my $tmp2 ( @sample2 ) {
  print $tmp2 ;
}

print "\n";

# whileで要素を変数にshiftさせる
while( my $tmp3 = shift( @sample3 ) ) {
  print $tmp3;
}

print "\n";

# 繰り返しを使わないでprint 
print @sample;
print "\n";
# スペース区切りで出力
print "@sample";
print "\n";

実行結果

abc
abc
abc
abc
abc
a b c

連想配列

定義

連想配列の定義には%を使います。配列と同様に連想配列の定義にはいくつか方法があります。下記ではカンマ区切りでの順番、ファットコロンアロー演算子、添字での指定について記述します。※2012/5/24追記:アロー演算子は->は意味していました。=>でファットコロンと呼ぶようです。@akajiroさんからご指摘を頂きました。

#!/usr/local/bin/perl -w

use strict;
use warnings;

# %を使う key,valueの繰り返し
my %sample = ( '0', 'a', '1', 'b', '2', 'c' );

# ファットコンマ
my %sample2 = ( '0' => 'a', '1' => 'b', '2' => 'c' );

# $を使う
my %sample3;
$sample2{'0'} = 'a';
$sample2{'1'} = 'b';
$sample2{'2'} = 'c';
取得

連想配列のkey,valueを取得するにはforeachとkeys関数の組み合わせかwhileとeach関数の組み合わせで記述されることが多いようです。keys関数は連想配列のkeyを変数に展開、values関数は値だけを変数に展開、eachはkeyと値の両方を展開します。keysやvalues関数を掛けた結果に対し更にスカラー展開すると連想配列の大きさを取得する事ができます。また連想配列の取得は何も指定しないとランダムになるのでforeachとsort関数を使うとkeyをsortできます。

#!/usr/local/bin/perl -w

use strict;
use warnings;

# %を使う key,valueの繰り返し
my %sample = ( '0', 'a', '1', 'b', '2', 'c' );

# アロー演算子を使う
my %sample2 = ( '0' => 'a', '1' => 'b', '2' => 'c' );

# $を使う
my %sample3;
$sample2{'0'} = 'a';
$sample2{'1'} = 'b';
$sample2{'2'} = 'c';


# foreachとkeysを使う 
foreach my $key( keys %sample ) {
  print "Key = $key  Value = $sample{$key} \n"; 
}

print "\n";

# whileとeachを使う
while( ( my $key, my $value ) = each( %sample2 ) ) {
  print "Key = $key  Value = $value \n";
}

print "\n";

# keyでsortする
foreach my $key( sort keys %sample ) {
  print "Key = $key  Value = $sample{$key} \n"; 
}

print "\n";

# valueだけを取得
my @value = values( %sample );
print "@value";

# ハッシュの長さを求める
print "\n\n";
my $length = values( %sample );
print $length;

実行結果

Key = 1  Value = b 
Key = 0  Value = a 
Key = 2  Value = c 

Key = 1  Value = b 
Key = 0  Value = a 
Key = 2  Value = c 

Key = 0  Value = a 
Key = 1  Value = b 
Key = 2  Value = c 

b a c

3

多次元連想配列

配列に連想配列を追加

上で記載した配列と連想配列を組み合わせて使います。まずは配列の中に連想配列を追加するような定義を行います。@配列で定義してpushで%ハッシュを追加します。注意が必要なのがpush( @array, %hash )と操作を行っても思うように追加されません。配列にハッシュを追加するためにはpush( @array, \%hash )と\を使って連想配列のリファレンスを渡す必要があります。リファレンスとはCのポインタのようなもので値が格納されているアドレスです。定義した配列の中の連想配列を取り出すときに連想配列のリファレンスが取得できるので、keyを取得するために連想配列デリファレンスを利用します。デリファレンスとは文字通りリファレンスの逆で格納アドレスから値を引く事です。連想配列の場合%$ハッシュとすることでアドレスから格納されている値に変換します。

#!/usr/local/bin/perl -w

use strict;
use warnings;

# 配列,連想配列の組み合わせ
my @array = (); 
my %hash1 = ( 'Key1' => 'Value1' );
my %hash2 = ( 'Key2' => 'Value2' );

# 配列に連想配列を追加
push( @array, \%hash1 );
push( @array, \%hash2 );

# foreachで取得
foreach my $tmp( @array ) { 
   foreach my $key( keys %$tmp ) { 
        print "Key = $key Value = $tmp->{$key} \n";
   }   
}

実行結果

Key = Key1 Value = Value1 
Key = Key2 Value = Value2
連想配列に配列を追加

上とは逆に連想配列に配列を追加します。配列のリファレンスを連想配列スカラーに渡し、foreachで取得する際に配列のデリファレンスを行います。

#!/usr/local/bin/perl -w

use strict;
use warnings;

# 配列,連想配列の組み合わせ
my %hash = ();
my @array1 = ( 'a', 'b', 'c' );
my @array2 = ( 'd', 'e', 'f' );

# 連想配列に配列を追加
$hash{ "Key1" } = \@array1;
$hash{ "Key2" } = \@array2;

# foreachで取得
foreach my $key( sort keys %hash ) {
   print "Key = $key";
   foreach my $data( $hash{$key} ) {
        print " Value = @$data";
   }
   print "\n";
}

実行結果

Key = Key1 Value = a b c
Key = Key2 Value = d e f

Json Encode

配列の中の連想配列連想配列の中の配列の両方が定義出来たのでそれらをJSON化します。JSONにするにはいくつか方法があり、JSON::Syck、JSON::XSというモジュールか use JSON qw/encode_json decode_json/、 use JSON qw/to_json from_json/を指定するようです。下ではencode_jsonを使ってJSONに変換します。encode_jsonには配列や連想配列のリファレンスを渡さないとエラーが発生するので注意が必要です。

#!/usr/local/bin/perl -w

use strict;
use warnings;
use JSON;

# 配列,連想配列の組み合わせ
my @array = ();
my %hash1 = ( 'Key1' => 'Value1' );
my %hash2 = ( 'Key2' => 'Value2' );

# 配列に連想配列を追加
push( @array, \%hash1 );
push( @array, \%hash2 );

# foreachで取得
foreach my $tmp( @array ) {
   foreach my $key( keys %$tmp ) {
        print "Key = $key Value = $tmp->{$key} \n";
   }
}

# json化する 配列のリファレンスを渡す必要がある
print encode_json( \@array );

実行結果

Key = Key1 Value = Value1 
Key = Key2 Value = Value2 
[{"Key1":"Value1"},{"Key2":"Value2"}]