« さすらいペット旅情編2が停止中 | メイン | さすらいペット旅情編2が復旧 »

2005年 6月 16日(木)   友引  今日は何の日?

複雑なデータをBerkeleyDBへ入れる - MLDBM - の続き

Category : Perl 

※記事の後半を失ってしまいました。修復可能な範囲で修復を試みました。

複雑なデータをBerkeleyDBへ入れる - MLDBM -の記事を読んだ方から、 読み込んだ後で、項目毎にソートして取り出すには、どうすれば良いのか?
と言うお問い合わせを頂きました。その疑問に対する対応例を示したいと思います。

これは、MLDBMを利用したから。と言う事よりも、リファレンスを利用した複雑なデータ構造をソートするのには、 どうしたら良いのか?と言う疑問と同じ事だとは思います。Web上には、僕の説明よりもっと丁寧な説明がたくさんあると思うので、 その様な説明も参考にしつつお読み頂ければと思います。

リファレンスを利用した複雑なデータ構造であっても、Perlでデータのソートを行いたい場合には、 sortと言うPerl組み込みの命令を利用する方法が一番良いと思います。
sortは複数の利用方法がありますが、一番汎用性の高い使い方は、

@array = sort 関数 @array;

と言う使い方です。関数の部分に、ソート順に対応する記述を行います。では、 実際にMLDBMでデータを読み込んでそれをソートして表示する例を示してみましょう。なお、この例は、複雑なデータをBerkeleyDBへ入れる - MLDBM -の記事で示した、 データ(MLDBMで書き出したデータ)を読み込んで居ます。利用したデータ, BerkeleyDBへの書き出し部分については複雑なデータをBerkeleyDBへ入れる - MLDBM -の記事を参照してください。

#!/usr/bin/perl

use strict;
use AnyDBM_File;
use MLDBM qw (AnyDBM_File);
use Fcntl;

my($db, @f, @array);

$db = 'data_mldbm.db';
@f  = qw(data_mldbm_0.txt
         data_mldbm_1.txt
         data_mldbm_2.txt);

&load_db($db, \@array);
&dump_data(\@array, $f[0]);
@array = sort sortsub1 @array;
&dump_data(\@array, $f[1]);
@array = sort sortsub2 @array;
&dump_data(\@array, $f[2]);

exit(0);


sub load_db($$) {
  my($db, $array) = @_;
  my(%hash, $rec);

  tie(%hash, 'MLDBM', $db, O_RDONLY, 0666);
  foreach $rec (keys %hash) {
    $array[$hash{$rec}{'no'}] = $hash{$rec};
  }
  untie(%hash);
}


sub sortsub1 {
  $a->{bday}->{ymd} <=> $b->{bday}->{ymd} ||
  $b->{data1}       cmp $a->{data1}       ||
  $a->{data2}       cmp $b->{data2}       ||
  $a->{email}       cmp $b->{email}       ||
  $a->{no}          <=> $b->{no}
}


sub sortsub2 {
  $a->{bday}->{mm}  <=> $b->{bday}->{mm}  ||
  $a->{bday}->{ymd} <=> $b->{bday}->{ymd} ||
  $a                cmp $b
}


sub dump_data($$) {
  my($array, $f) = @_;
  my($i, $j, $k, @s);

  for ($i = 0; $i <= scalar(@{$array})-1; $i++) {
    foreach $j (sort keys %{$array[$i]}) {
      if (ref($array[$i]{$j}) eq 'HASH') {
        foreach $k (sort keys %{$array[$i]{$j}}) {
          push(@s,
            sprintf("(%2d)  %-6s->%-6s => ", $i, $j, $k).
            $array[$i]{$j}{$k});
        }
      }
      else {
        push(@s,
          sprintf("(%2d)  %-6s         => ", $i, $j).
          $array[$i]{$j});
      }
    }
    push(@s, "");
  }

  open(OUT, "> $f") or die("open error $f");
  foreach (@s) {
    print $_. "\n";
    print OUT $_. "\n";
  }
  close(OUT);
}


__END__;

基本的には、複雑なデータをBerkeleyDBへ入れる - MLDBM -の記事で示したデータベースの読み込み処理と同じです。 dump_dataを修正して結果をテキストファイルに落とせる様にしておきました。

sortで呼び出す関数では、$a, $bが仮引数として利用される。と言う決まりがあります。 常に$aと$bを通して比較がなされます。sort関数の内側では、$a, $bを修正してはならない。など、幾つかの決まりがあります。 詳しくはPerlのリファレンスを確認してください。
複数の条件がある場合には、優先順位の高い条件から順番に条件を記述します。条件は||で繋げます。(正確には、 もう少しいろいろとありますが。。。)
リファレンスで複雑なデータ構造を持っている場合には、

$a->{'キー名称'}->{'キー名称'}->{'キー名称'}

の様に、->演算子で繋げて指定する様にします。
sort1関数の様に、ハッシュへのリファレンス, ハッシュへのリファレンスのリファレンスの様に、 複数の型を||で連ねて条件を指定する事で、複雑な条件でも指定する事ができます。

$a->{'キー項目'} <=> $b->{'キー項目'}

とすると、昇順に並び、

$b->{'キー項目'} <=> $a->{'キー項目'}

とすれば、降順に並びます。この様な決まりに従ってソート条件を指定する事で、このみの順序で取り出す事ができる様になります。

では、実際に出力されたデータを見てみましょう。まずは、ソートを行っていない結果です。

( 1)  bday  ->day    => 1963/04/01
( 1)  bday  ->dd     => 01
( 1)  bday  ->mm     => 04
( 1)  bday  ->org    => 1963/4/ 1
( 1)  bday  ->ymd    => 19630401
( 1)  bday  ->yy     => 1963
( 1)  bday0          => 1963/04/30
( 1)  data1          => AAAA
( 1)  data2          => AA
( 1)  email          => a1@a.ne.jp
( 1)  no             => 1

( 2)  bday  ->day    => 1963/04/01
( 2)  bday  ->dd     => 01
( 2)  bday  ->mm     => 04
( 2)  bday  ->org    => 1963/4/ 1
( 2)  bday  ->ymd    => 19630401
( 2)  bday  ->yy     => 1963
( 2)  bday0          => 1964/01/15
( 2)  data1          => AAAA
( 2)  data2          => BB
( 2)  email          => a2@a.ne.jp
( 2)  no             => 2

( 3)  bday  ->day    => 1963/04/01
( 3)  bday  ->dd     => 01
( 3)  bday  ->mm     => 04
( 3)  bday  ->org    => 1963/4/ 1
( 3)  bday  ->ymd    => 19630401
( 3)  bday  ->yy     => 1963
( 3)  bday0          => 1968/10/23
( 3)  data1          => BBBB
( 3)  data2          => AA
( 3)  email          => a3@a.ne.jp
( 3)  no             => 3

( 4)  bday  ->day    => 1963/04/01
( 4)  bday  ->dd     => 01
( 4)  bday  ->mm     => 04
( 4)  bday  ->org    => 1963/4/ 1
( 4)  bday  ->ymd    => 19630401
( 4)  bday  ->yy     => 1963
( 4)  bday0          => 1961/01/10
( 4)  data1          => AAAA
( 4)  data2          => BB
( 4)  email          => a4@a.ne.jp
( 4)  no             => 4

( 5)  bday  ->day    => 1963/04/01
( 5)  bday  ->dd     => 01
( 5)  bday  ->mm     => 04
( 5)  bday  ->org    => 1963/4/ 1
( 5)  bday  ->ymd    => 19630401
( 5)  bday  ->yy     => 1963
( 5)  bday0          => 1964/01/16
( 5)  data1          => BBBB
( 5)  data2          => BB
( 5)  email          => a5@a.ne.jp
( 5)  no             => 5

( 6)  bday  ->day    => 1963/04/01
( 6)  bday  ->dd     => 01
( 6)  bday  ->mm     => 04
( 6)  bday  ->org    => 1963/4/ 1
( 6)  bday  ->ymd    => 19630401
( 6)  bday  ->yy     => 1963
( 6)  bday0          => 1967/05/14
( 6)  data1          => BBBB
( 6)  data2          => AA
( 6)  email          => a6@a.ne.jp
( 6)  no             => 6

( 7)  bday  ->day    => 1963/04/01
( 7)  bday  ->dd     => 01
( 7)  bday  ->mm     => 04
( 7)  bday  ->org    => 1963/4/ 1
( 7)  bday  ->ymd    => 19630401
( 7)  bday  ->yy     => 1963
( 7)  bday0          => 1963/04/30
( 7)  data1          => AAAA
( 7)  data2          => AA
( 7)  email          => a7@a.ne.jp
( 7)  no             => 7

( 8)  bday  ->day    => 1963/04/01
( 8)  bday  ->dd     => 01
( 8)  bday  ->mm     => 04
( 8)  bday  ->org    => 1963/4/ 1
( 8)  bday  ->ymd    => 19630401
( 8)  bday  ->yy     => 1963
( 8)  bday0          => 1966/03/14
( 8)  data1          => AAAA
( 8)  data2          => BB
( 8)  email          => a8@a.ne.jp
( 8)  no             => 8

( 9)  bday  ->day    => 1963/04/01
( 9)  bday  ->dd     => 01
( 9)  bday  ->mm     => 04
( 9)  bday  ->org    => 1963/4/ 1
( 9)  bday  ->ymd    => 19630401
( 9)  bday  ->yy     => 1963
( 9)  bday0          => 1968/10/23
( 9)  data1          => BBBB
( 9)  data2          => AA
( 9)  email          => a9@a.ne.jp
( 9)  no             => 9

(10)  bday  ->day    => 1963/04/01
(10)  bday  ->dd     => 01
(10)  bday  ->mm     => 04
(10)  bday  ->org    => 1963/4/ 1
(10)  bday  ->ymd    => 19630401
(10)  bday  ->yy     => 1963
(10)  bday0          => 1967/09/07
(10)  data1          => BBBB
(10)  data2          => BB
(10)  email          => a10@a.ne.jp
(10)  no             => 10

:

dump_dataで登録番号順に取り出して表示する様にしてあるので、この様な並びになります。次に、 sort1の条件で並べた結果です。

( 1)  bday  ->day    => 1963/04/01
( 1)  bday  ->dd     => 01
( 1)  bday  ->mm     => 04
( 1)  bday  ->org    => 1963/4/ 1
( 1)  bday  ->ymd    => 19630401
( 1)  bday  ->yy     => 1963
( 1)  bday0          => 1967/09/07
( 1)  data1          => BBBB
( 1)  data2          => AA
( 1)  email          => a13@a.ne.jp
( 1)  no             => 13

( 2)  bday  ->day    => 1963/04/01
( 2)  bday  ->dd     => 01
( 2)  bday  ->mm     => 04
( 2)  bday  ->org    => 1963/4/ 1
( 2)  bday  ->ymd    => 19630401
( 2)  bday  ->yy     => 1963
( 2)  bday0          => 1963/04/30
( 2)  data1          => BBBB
( 2)  data2          => AA
( 2)  email          => a14@a.ne.jp
( 2)  no             => 14

( 3)  bday  ->day    => 1963/04/01
( 3)  bday  ->dd     => 01
( 3)  bday  ->mm     => 04
( 3)  bday  ->org    => 1963/4/ 1
( 3)  bday  ->ymd    => 19630401
( 3)  bday  ->yy     => 1963
( 3)  bday0          => 1967/09/07
( 3)  data1          => BBBB
( 3)  data2          => AA
( 3)  email          => a19@a.ne.jp
( 3)  no             => 19

( 4)  bday  ->day    => 1963/04/01
( 4)  bday  ->dd     => 01
( 4)  bday  ->mm     => 04
( 4)  bday  ->org    => 1963/4/ 1
( 4)  bday  ->ymd    => 19630401
( 4)  bday  ->yy     => 1963
( 4)  bday0          => 1968/05/13
( 4)  data1          => BBBB
( 4)  data2          => AA
( 4)  email          => a20@a.ne.jp
( 4)  no             => 20

( 5)  bday  ->day    => 1963/04/01
( 5)  bday  ->dd     => 01
( 5)  bday  ->mm     => 04
( 5)  bday  ->org    => 1963/4/ 1
( 5)  bday  ->ymd    => 19630401
( 5)  bday  ->yy     => 1963
( 5)  bday0          => 1968/10/23
( 5)  data1          => BBBB
( 5)  data2          => AA
( 5)  email          => a3@a.ne.jp
( 5)  no             => 3

( 6)  bday  ->day    => 1963/04/01
( 6)  bday  ->dd     => 01
( 6)  bday  ->mm     => 04
( 6)  bday  ->org    => 1963/4/ 1
( 6)  bday  ->ymd    => 19630401
( 6)  bday  ->yy     => 1963
( 6)  bday0          => 1967/05/14
( 6)  data1          => BBBB
( 6)  data2          => AA
( 6)  email          => a6@a.ne.jp
( 6)  no             => 6

( 7)  bday  ->day    => 1963/04/01
( 7)  bday  ->dd     => 01
( 7)  bday  ->mm     => 04
( 7)  bday  ->org    => 1963/4/ 1
( 7)  bday  ->ymd    => 19630401
( 7)  bday  ->yy     => 1963
( 7)  bday0          => 1968/10/23
( 7)  data1          => BBBB
( 7)  data2          => AA
( 7)  email          => a9@a.ne.jp
( 7)  no             => 9

( 8)  bday  ->day    => 1963/04/01
( 8)  bday  ->dd     => 01
( 8)  bday  ->mm     => 04
( 8)  bday  ->org    => 1963/4/ 1
( 8)  bday  ->ymd    => 19630401
( 8)  bday  ->yy     => 1963
( 8)  bday0          => 1967/09/07
( 8)  data1          => BBBB
( 8)  data2          => BB
( 8)  email          => a10@a.ne.jp
( 8)  no             => 10

( 9)  bday  ->day    => 1963/04/01
( 9)  bday  ->dd     => 01
( 9)  bday  ->mm     => 04
( 9)  bday  ->org    => 1963/4/ 1
( 9)  bday  ->ymd    => 19630401
( 9)  bday  ->yy     => 1963
( 9)  bday0          => 1964/01/16
( 9)  data1          => BBBB
( 9)  data2          => BB
( 9)  email          => a18@a.ne.jp
( 9)  no             => 18

(10)  bday  ->day    => 1963/04/01
(10)  bday  ->dd     => 01
(10)  bday  ->mm     => 04
(10)  bday  ->org    => 1963/4/ 1
(10)  bday  ->ymd    => 19630401
(10)  bday  ->yy     => 1963
(10)  bday0          => 1964/01/16
(10)  data1          => BBBB
(10)  data2          => BB
(10)  email          => a5@a.ne.jp
(10)  no             => 5

:

複雑なデータ構造でも、意図した順序で並んでいると思います。昇順, 降順の違いも気にしながら結果を見てください。次に、 sort2を実行した結果です。

( 1)  bday  ->day    => 1963/04/01
( 1)  bday  ->dd     => 01
( 1)  bday  ->mm     => 04
( 1)  bday  ->org    => 1963/4/ 1
( 1)  bday  ->ymd    => 19630401
( 1)  bday  ->yy     => 1963
( 1)  bday0          => 1963/04/30
( 1)  data1          => AAAA
( 1)  data2          => AA
( 1)  email          => a1@a.ne.jp
( 1)  no             => 1

( 2)  bday  ->day    => 1963/04/01
( 2)  bday  ->dd     => 01
( 2)  bday  ->mm     => 04
( 2)  bday  ->org    => 1963/4/ 1
( 2)  bday  ->ymd    => 19630401
( 2)  bday  ->yy     => 1963
( 2)  bday0          => 1963/04/30
( 2)  data1          => AAAA
( 2)  data2          => AA
( 2)  email          => a7@a.ne.jp
( 2)  no             => 7

( 3)  bday  ->day    => 1963/04/01
( 3)  bday  ->dd     => 01
( 3)  bday  ->mm     => 04
( 3)  bday  ->org    => 1963/4/ 1
( 3)  bday  ->ymd    => 19630401
( 3)  bday  ->yy     => 1963
( 3)  bday0          => 1968/10/23
( 3)  data1          => BBBB
( 3)  data2          => AA
( 3)  email          => a9@a.ne.jp
( 3)  no             => 9

( 4)  bday  ->day    => 1963/04/01
( 4)  bday  ->dd     => 01
( 4)  bday  ->mm     => 04
( 4)  bday  ->org    => 1963/4/ 1
( 4)  bday  ->ymd    => 19630401
( 4)  bday  ->yy     => 1963
( 4)  bday0          => 1967/09/07
( 4)  data1          => BBBB
( 4)  data2          => BB
( 4)  email          => a10@a.ne.jp
( 4)  no             => 10

( 5)  bday  ->day    => 1963/04/01
( 5)  bday  ->dd     => 01
( 5)  bday  ->mm     => 04
( 5)  bday  ->org    => 1963/4/ 1
( 5)  bday  ->ymd    => 19630401
( 5)  bday  ->yy     => 1963
( 5)  bday0          => 1967/11/21
( 5)  data1          => AAAA
( 5)  data2          => AA
( 5)  email          => a12@a.ne.jp
( 5)  no             => 12

( 6)  bday  ->day    => 1963/04/01
( 6)  bday  ->dd     => 01
( 6)  bday  ->mm     => 04
( 6)  bday  ->org    => 1963/4/ 1
( 6)  bday  ->ymd    => 19630401
( 6)  bday  ->yy     => 1963
( 6)  bday0          => 1963/04/30
( 6)  data1          => BBBB
( 6)  data2          => AA
( 6)  email          => a14@a.ne.jp
( 6)  no             => 14

( 7)  bday  ->day    => 1963/04/01
( 7)  bday  ->dd     => 01
( 7)  bday  ->mm     => 04
( 7)  bday  ->org    => 1963/4/ 1
( 7)  bday  ->ymd    => 19630401
( 7)  bday  ->yy     => 1963
( 7)  bday0          => 1964/01/16
( 7)  data1          => BBBB
( 7)  data2          => BB
( 7)  email          => a5@a.ne.jp
( 7)  no             => 5

( 8)  bday  ->day    => 1963/04/01
( 8)  bday  ->dd     => 01
( 8)  bday  ->mm     => 04
( 8)  bday  ->org    => 1963/4/ 1
( 8)  bday  ->ymd    => 19630401
( 8)  bday  ->yy     => 1963
( 8)  bday0          => 1968/10/23
( 8)  data1          => BBBB
( 8)  data2          => AA
( 8)  email          => a3@a.ne.jp
( 8)  no             => 3

( 9)  bday  ->day    => 1963/04/01
( 9)  bday  ->dd     => 01
( 9)  bday  ->mm     => 04
( 9)  bday  ->org    => 1963/4/ 1
( 9)  bday  ->ymd    => 19630401
( 9)  bday  ->yy     => 1963
( 9)  bday0          => 1964/01/11
( 9)  data1          => AAAA
( 9)  data2          => BB
( 9)  email          => a16@a.ne.jp
( 9)  no             => 16

(10)  bday  ->day    => 1963/04/01
(10)  bday  ->dd     => 01
(10)  bday  ->mm     => 04
(10)  bday  ->org    => 1963/4/ 1
(10)  bday  ->ymd    => 19630401
(10)  bday  ->yy     => 1963
(10)  bday0          => 1964/01/16
(10)  data1          => BBBB
(10)  data2          => BB
(10)  email          => a18@a.ne.jp
(10)  no             => 18

:

の様になります。

Posted by kibiwaka : 2005年06月16日 16:21

トラックバック

  • トラックバックを頂く記事の内容については、記事に関係する内容、記事への同調、記事への反論など、 記事の内容に関するもののみとします。
  • トラックバック先の記事に、当サイト、または該当記事へのリンクが無い場合には、トラックバックを削除させていただく場合があります。
  • Movable Typeの迷惑トラックバック感知機能により、トラックバックが受け付けられない場合があります。
  • 法律に触れる可能性があると判断できるもの、当サイトへの掲載が不適当と思われる内容については、 事前の連絡をなしに削除する場合があります。
  • 当サイト、黍若個人への連絡事項などがあれば、連絡用記事へトラックバックを付けてください。 個別の記事に付けないで下さい。
    または、ウェブメールでご連絡下さい。
  • 詳しくし、黍若日記 コメント・トラックバック・リンク基本方針をご覧下さい。

このエントリーのトラックバックURL:


このエントリーのリンク用URL:


コメント

  • コメントを頂く記事の内容については、記事に関係する内容、記事への同調、記事への反論など、 記事の内容に関するもののみとします。
  • Movable Typeの迷惑コメント感知機能により、コメントが受け付けられない場合があります。
  • 法律に触れる可能性があると判断できるもの、当サイトへの掲載が不適当と思われる内容については、 事前の連絡をなしに削除する場合があります。
  • 当サイト、黍若個人への連絡事項などがあれば、連絡用記事へコメントを付けてください。 個別の記事に付けないで下さい。
    または、ウェブメールでご連絡下さい。
  • 詳しくし、黍若日記 コメント・トラックバック・リンク基本方針をご覧下さい。

コメントしてください




保存しますか?