1PERLDSC(1)             Perl Programmers Reference Guide             PERLDSC(1)
2
3
4

NAME

6       perldsc - Perl Data Structures Cookbook
7

DESCRIPTION

9       Perl lets us have complex data structures.  You can write something
10       like this and all of a sudden, you'd have an array with three
11       dimensions!
12
13           for my $x (1 .. 10) {
14               for my $y (1 .. 10) {
15                   for my $z (1 .. 10) {
16                       $AoA[$x][$y][$z] =
17                           $x ** $y + $z;
18                   }
19               }
20           }
21
22       Alas, however simple this may appear, underneath it's a much more
23       elaborate construct than meets the eye!
24
25       How do you print it out?  Why can't you say just "print @AoA"?  How do
26       you sort it?  How can you pass it to a function or get one of these
27       back from a function?  Is it an object?  Can you save it to disk to
28       read back later?  How do you access whole rows or columns of that
29       matrix?  Do all the values have to be numeric?
30
31       As you see, it's quite easy to become confused.  While some small
32       portion of the blame for this can be attributed to the reference-based
33       implementation, it's really more due to a lack of existing
34       documentation with examples designed for the beginner.
35
36       This document is meant to be a detailed but understandable treatment of
37       the many different sorts of data structures you might want to develop.
38       It should also serve as a cookbook of examples.  That way, when you
39       need to create one of these complex data structures, you can just
40       pinch, pilfer, or purloin a drop-in example from here.
41
42       Let's look at each of these possible constructs in detail.  There are
43       separate sections on each of the following:
44
45       •    arrays of arrays
46
47       •    hashes of arrays
48
49       •    arrays of hashes
50
51       •    hashes of hashes
52
53       •    more elaborate constructs
54
55       But for now, let's look at general issues common to all these types of
56       data structures.
57

REFERENCES

59       The most important thing to understand about all data structures in
60       Perl--including multidimensional arrays--is that even though they might
61       appear otherwise, Perl @ARRAYs and %HASHes are all internally one-
62       dimensional.  They can hold only scalar values (meaning a string,
63       number, or a reference).  They cannot directly contain other arrays or
64       hashes, but instead contain references to other arrays or hashes.
65
66       You can't use a reference to an array or hash in quite the same way
67       that you would a real array or hash.  For C or C++ programmers unused
68       to distinguishing between arrays and pointers to the same, this can be
69       confusing.  If so, just think of it as the difference between a
70       structure and a pointer to a structure.
71
72       You can (and should) read more about references in perlref.  Briefly,
73       references are rather like pointers that know what they point to.
74       (Objects are also a kind of reference, but we won't be needing them
75       right away--if ever.)  This means that when you have something which
76       looks to you like an access to a two-or-more-dimensional array and/or
77       hash, what's really going on is that the base type is merely a one-
78       dimensional entity that contains references to the next level.  It's
79       just that you can use it as though it were a two-dimensional one.  This
80       is actually the way almost all C multidimensional arrays work as well.
81
82           $array[7][12]                       # array of arrays
83           $array[7]{string}                   # array of hashes
84           $hash{string}[7]                    # hash of arrays
85           $hash{string}{'another string'}     # hash of hashes
86
87       Now, because the top level contains only references, if you try to
88       print out your array in with a simple print() function, you'll get
89       something that doesn't look very nice, like this:
90
91           my @AoA = ( [2, 3], [4, 5, 7], [0] );
92           print $AoA[1][2];
93         7
94           print @AoA;
95         ARRAY(0x83c38)ARRAY(0x8b194)ARRAY(0x8b1d0)
96
97       That's because Perl doesn't (ever) implicitly dereference your
98       variables.  If you want to get at the thing a reference is referring
99       to, then you have to do this yourself using either prefix typing
100       indicators, like "${$blah}", "@{$blah}", "@{$blah[$i]}", or else
101       postfix pointer arrows, like "$a->[3]", "$h->{fred}", or even
102       "$ob->method()->[3]".
103

COMMON MISTAKES

105       The two most common mistakes made in constructing something like an
106       array of arrays is either accidentally counting the number of elements
107       or else taking a reference to the same memory location repeatedly.
108       Here's the case where you just get the count instead of a nested array:
109
110           for my $i (1..10) {
111               my @array = somefunc($i);
112               $AoA[$i] = @array;      # WRONG!
113           }
114
115       That's just the simple case of assigning an array to a scalar and
116       getting its element count.  If that's what you really and truly want,
117       then you might do well to consider being a tad more explicit about it,
118       like this:
119
120           for my $i (1..10) {
121               my @array = somefunc($i);
122               $counts[$i] = scalar @array;
123           }
124
125       Here's the case of taking a reference to the same memory location again
126       and again:
127
128           # Either without strict or having an outer-scope my @array;
129           # declaration.
130
131           for my $i (1..10) {
132               @array = somefunc($i);
133               $AoA[$i] = \@array;     # WRONG!
134           }
135
136       So, what's the big problem with that?  It looks right, doesn't it?
137       After all, I just told you that you need an array of references, so by
138       golly, you've made me one!
139
140       Unfortunately, while this is true, it's still broken.  All the
141       references in @AoA refer to the very same place, and they will
142       therefore all hold whatever was last in @array!  It's similar to the
143       problem demonstrated in the following C program:
144
145           #include <pwd.h>
146           main() {
147               struct passwd *getpwnam(), *rp, *dp;
148               rp = getpwnam("root");
149               dp = getpwnam("daemon");
150
151               printf("daemon name is %s\nroot name is %s\n",
152                       dp->pw_name, rp->pw_name);
153           }
154
155       Which will print
156
157           daemon name is daemon
158           root name is daemon
159
160       The problem is that both "rp" and "dp" are pointers to the same
161       location in memory!  In C, you'd have to remember to malloc() yourself
162       some new memory.  In Perl, you'll want to use the array constructor
163       "[]" or the hash constructor "{}" instead.   Here's the right way to do
164       the preceding broken code fragments:
165
166           # Either without strict or having an outer-scope my @array;
167           # declaration.
168
169           for my $i (1..10) {
170               @array = somefunc($i);
171               $AoA[$i] = [ @array ];
172           }
173
174       The square brackets make a reference to a new array with a copy of
175       what's in @array at the time of the assignment.  This is what you want.
176
177       Note that this will produce something similar:
178
179           # Either without strict or having an outer-scope my @array;
180           # declaration.
181           for my $i (1..10) {
182               @array = 0 .. $i;
183               $AoA[$i]->@* = @array;
184           }
185
186       Is it the same?  Well, maybe so--and maybe not.  The subtle difference
187       is that when you assign something in square brackets, you know for sure
188       it's always a brand new reference with a new copy of the data.
189       Something else could be going on in this new case with the
190       "$AoA[$i]->@*" dereference on the left-hand-side of the assignment.  It
191       all depends on whether $AoA[$i] had been undefined to start with, or
192       whether it already contained a reference.  If you had already populated
193       @AoA with references, as in
194
195           $AoA[3] = \@another_array;
196
197       Then the assignment with the indirection on the left-hand-side would
198       use the existing reference that was already there:
199
200           $AoA[3]->@* = @array;
201
202       Of course, this would have the "interesting" effect of clobbering
203       @another_array.  (Have you ever noticed how when a programmer says
204       something is "interesting", that rather than meaning "intriguing",
205       they're disturbingly more apt to mean that it's "annoying",
206       "difficult", or both?  :-)
207
208       So just remember always to use the array or hash constructors with "[]"
209       or "{}", and you'll be fine, although it's not always optimally
210       efficient.
211
212       Surprisingly, the following dangerous-looking construct will actually
213       work out fine:
214
215           for my $i (1..10) {
216               my @array = somefunc($i);
217               $AoA[$i] = \@array;
218           }
219
220       That's because my() is more of a run-time statement than it is a
221       compile-time declaration per se.  This means that the my() variable is
222       remade afresh each time through the loop.  So even though it looks as
223       though you stored the same variable reference each time, you actually
224       did not!  This is a subtle distinction that can produce more efficient
225       code at the risk of misleading all but the most experienced of
226       programmers.  So I usually advise against teaching it to beginners.  In
227       fact, except for passing arguments to functions, I seldom like to see
228       the gimme-a-reference operator (backslash) used much at all in code.
229       Instead, I advise beginners that they (and most of the rest of us)
230       should try to use the much more easily understood constructors "[]" and
231       "{}" instead of relying upon lexical (or dynamic) scoping and hidden
232       reference-counting to do the right thing behind the scenes.
233
234       Note also that there exists another way to write a dereference!  These
235       two lines are equivalent:
236
237           $AoA[$i]->@* = @array;
238           @{ $AoA[$i] } = @array;
239
240       The first form, called postfix dereference is generally easier to read,
241       because the expression can be read from left to right, and there are no
242       enclosing braces to balance.  On the other hand, it is also newer.  It
243       was added to the language in 2014, so you will often encounter the
244       other form, circumfix dereference, in older code.
245
246       In summary:
247
248           $AoA[$i] = [ @array ];     # usually best
249           $AoA[$i] = \@array;        # perilous; just how my() was that array?
250           $AoA[$i]->@*  = @array;    # way too tricky for most programmers
251           @{ $AoA[$i] } = @array;    # just as tricky, and also harder to read
252

CAVEAT ON PRECEDENCE

254       Speaking of things like "@{$AoA[$i]}", the following are actually the
255       same thing:
256
257           $aref->[2][2]       # clear
258           $$aref[2][2]        # confusing
259
260       That's because Perl's precedence rules on its five prefix dereferencers
261       (which look like someone swearing: "$ @ * % &") make them bind more
262       tightly than the postfix subscripting brackets or braces!  This will no
263       doubt come as a great shock to the C or C++ programmer, who is quite
264       accustomed to using *a[i] to mean what's pointed to by the i'th element
265       of "a".  That is, they first take the subscript, and only then
266       dereference the thing at that subscript.  That's fine in C, but this
267       isn't C.
268
269       The seemingly equivalent construct in Perl, $$aref[$i] first does the
270       deref of $aref, making it take $aref as a reference to an array, and
271       then dereference that, and finally tell you the i'th value of the array
272       pointed to by $AoA. If you wanted the C notion, you could write
273       "$AoA[$i]->$*" to explicitly dereference the i'th item, reading left to
274       right.
275

WHY YOU SHOULD ALWAYS "use VERSION"

277       If this is starting to sound scarier than it's worth, relax.  Perl has
278       some features to help you avoid its most common pitfalls.  One way to
279       avoid getting confused is to start every program with:
280
281           use strict;
282
283       This way, you'll be forced to declare all your variables with my() and
284       also disallow accidental "symbolic dereferencing".  Therefore if you'd
285       done this:
286
287           my $aref = [
288               [ "fred", "barney", "pebbles", "bambam", "dino", ],
289               [ "homer", "bart", "marge", "maggie", ],
290               [ "george", "jane", "elroy", "judy", ],
291           ];
292
293           print $aref[2][2];
294
295       The compiler would immediately flag that as an error at compile time,
296       because you were accidentally accessing @aref, an undeclared variable,
297       and it would thereby remind you to write instead:
298
299           print $aref->[2][2]
300
301       Since Perl version 5.12, a "use VERSION" declaration will also enable
302       the "strict" pragma.  In addition, it will also enable a feature
303       bundle, giving more useful features.  Since version 5.36 it will also
304       enable the "warnings" pragma.  Often the best way to activate all these
305       things at once is to start a file with:
306
307           use v5.36;
308
309       In this way, every file will start with "strict", "warnings", and many
310       useful named features all switched on, as well as several older
311       features being switched off (such as "indirect").  For more
312       information, see "use VERSION" in perlfunc.
313

DEBUGGING

315       You can use the debugger's "x" command to dump out complex data
316       structures.  For example, given the assignment to $AoA above, here's
317       the debugger output:
318
319           DB<1> x $AoA
320           $AoA = ARRAY(0x13b5a0)
321              0  ARRAY(0x1f0a24)
322                 0  'fred'
323                 1  'barney'
324                 2  'pebbles'
325                 3  'bambam'
326                 4  'dino'
327              1  ARRAY(0x13b558)
328                 0  'homer'
329                 1  'bart'
330                 2  'marge'
331                 3  'maggie'
332              2  ARRAY(0x13b540)
333                 0  'george'
334                 1  'jane'
335                 2  'elroy'
336                 3  'judy'
337

CODE EXAMPLES

339       Presented with little comment here are short code examples illustrating
340       access of various types of data structures.
341

ARRAYS OF ARRAYS

343   Declaration of an ARRAY OF ARRAYS
344        my @AoA = (
345               [ "fred", "barney" ],
346               [ "george", "jane", "elroy" ],
347               [ "homer", "marge", "bart" ],
348             );
349
350   Generation of an ARRAY OF ARRAYS
351        # reading from file
352        while ( <> ) {
353            push @AoA, [ split ];
354        }
355
356        # calling a function
357        for my $i ( 1 .. 10 ) {
358            $AoA[$i] = [ somefunc($i) ];
359        }
360
361        # using temp vars
362        for my $i ( 1 .. 10 ) {
363            my @tmp = somefunc($i);
364            $AoA[$i] = [ @tmp ];
365        }
366
367        # add to an existing row
368        push $AoA[0]->@*, "wilma", "betty";
369
370   Access and Printing of an ARRAY OF ARRAYS
371        # one element
372        $AoA[0][0] = "Fred";
373
374        # another element
375        $AoA[1][1] =~ s/(\w)/\u$1/;
376
377        # print the whole thing with refs
378        for my $aref ( @AoA ) {
379            print "\t [ @$aref ],\n";
380        }
381
382        # print the whole thing with indices
383        for my $i ( 0 .. $#AoA ) {
384            print "\t [ $AoA[$i]->@* ],\n";
385        }
386
387        # print the whole thing one at a time
388        for my $i ( 0 .. $#AoA ) {
389            for my $j ( 0 .. $AoA[$i]->$#* ) {
390                print "elem at ($i, $j) is $AoA[$i][$j]\n";
391            }
392        }
393

HASHES OF ARRAYS

395   Declaration of a HASH OF ARRAYS
396        my %HoA = (
397               flintstones        => [ "fred", "barney" ],
398               jetsons            => [ "george", "jane", "elroy" ],
399               simpsons           => [ "homer", "marge", "bart" ],
400             );
401
402   Generation of a HASH OF ARRAYS
403        # reading from file
404        # flintstones: fred barney wilma dino
405        while ( <> ) {
406            next unless s/^(.*?):\s*//;
407            $HoA{$1} = [ split ];
408        }
409
410        # reading from file; more temps
411        # flintstones: fred barney wilma dino
412        while ( my $line = <> ) {
413            my ($who, $rest) = split /:\s*/, $line, 2;
414            my @fields = split ' ', $rest;
415            $HoA{$who} = [ @fields ];
416        }
417
418        # calling a function that returns a list
419        for my $group ( "simpsons", "jetsons", "flintstones" ) {
420            $HoA{$group} = [ get_family($group) ];
421        }
422
423        # likewise, but using temps
424        for my $group ( "simpsons", "jetsons", "flintstones" ) {
425            my @members = get_family($group);
426            $HoA{$group} = [ @members ];
427        }
428
429        # append new members to an existing family
430        push $HoA{flintstones}->@*, "wilma", "betty";
431
432   Access and Printing of a HASH OF ARRAYS
433        # one element
434        $HoA{flintstones}[0] = "Fred";
435
436        # another element
437        $HoA{simpsons}[1] =~ s/(\w)/\u$1/;
438
439        # print the whole thing
440        foreach my $family ( keys %HoA ) {
441            print "$family: $HoA{$family}->@* \n"
442        }
443
444        # print the whole thing with indices
445        foreach my $family ( keys %HoA ) {
446            print "family: ";
447            foreach my $i ( 0 .. $HoA{$family}->$#* ) {
448                print " $i = $HoA{$family}[$i]";
449            }
450            print "\n";
451        }
452
453        # print the whole thing sorted by number of members
454        foreach my $family ( sort { $HoA{$b}->@* <=> $HoA{$a}->@* } keys %HoA ) {
455            print "$family: $HoA{$family}->@* \n"
456        }
457
458        # print the whole thing sorted by number of members and name
459        foreach my $family ( sort {
460                                   $HoA{$b}->@* <=> $HoA{$a}->@*
461                                                 ||
462                                             $a cmp $b
463                   } keys %HoA )
464        {
465            print "$family: ", join(", ", sort $HoA{$family}->@* ), "\n";
466        }
467

ARRAYS OF HASHES

469   Declaration of an ARRAY OF HASHES
470        my @AoH = (
471               {
472                   Lead     => "fred",
473                   Friend   => "barney",
474               },
475               {
476                   Lead     => "george",
477                   Wife     => "jane",
478                   Son      => "elroy",
479               },
480               {
481                   Lead     => "homer",
482                   Wife     => "marge",
483                   Son      => "bart",
484               }
485         );
486
487   Generation of an ARRAY OF HASHES
488        # reading from file
489        # format: LEAD=fred FRIEND=barney
490        while ( <> ) {
491            my $rec = {};
492            for my $field ( split ) {
493                my ($key, $value) = split /=/, $field;
494                $rec->{$key} = $value;
495            }
496            push @AoH, $rec;
497        }
498
499
500        # reading from file
501        # format: LEAD=fred FRIEND=barney
502        # no temp
503        while ( <> ) {
504            push @AoH, { split /[\s+=]/ };
505        }
506
507        # calling a function  that returns a key/value pair list, like
508        # "lead","fred","daughter","pebbles"
509        while ( my %fields = getnextpairset() ) {
510            push @AoH, { %fields };
511        }
512
513        # likewise, but using no temp vars
514        while (<>) {
515            push @AoH, { parsepairs($_) };
516        }
517
518        # add key/value to an element
519        $AoH[0]{pet} = "dino";
520        $AoH[2]{pet} = "santa's little helper";
521
522   Access and Printing of an ARRAY OF HASHES
523        # one element
524        $AoH[0]{lead} = "fred";
525
526        # another element
527        $AoH[1]{lead} =~ s/(\w)/\u$1/;
528
529        # print the whole thing with refs
530        for my $href ( @AoH ) {
531            print "{ ";
532            for my $role ( keys %$href ) {
533                print "$role=$href->{$role} ";
534            }
535            print "}\n";
536        }
537
538        # print the whole thing with indices
539        for my $i ( 0 .. $#AoH ) {
540            print "$i is { ";
541            for my $role ( keys $AoH[$i]->%* ) {
542                print "$role=$AoH[$i]{$role} ";
543            }
544            print "}\n";
545        }
546
547        # print the whole thing one at a time
548        for my $i ( 0 .. $#AoH ) {
549            for my $role ( keys $AoH[$i]->%* ) {
550                print "elem at ($i, $role) is $AoH[$i]{$role}\n";
551            }
552        }
553

HASHES OF HASHES

555   Declaration of a HASH OF HASHES
556        my %HoH = (
557               flintstones => {
558                       lead      => "fred",
559                       pal       => "barney",
560               },
561               jetsons     => {
562                       lead      => "george",
563                       wife      => "jane",
564                       "his boy" => "elroy",
565               },
566               simpsons    => {
567                       lead      => "homer",
568                       wife      => "marge",
569                       kid       => "bart",
570               },
571        );
572
573   Generation of a HASH OF HASHES
574        # reading from file
575        # flintstones: lead=fred pal=barney wife=wilma pet=dino
576        while ( <> ) {
577            next unless s/^(.*?):\s*//;
578            my $who = $1;
579            for my $field ( split ) {
580                my ($key, $value) = split /=/, $field;
581                $HoH{$who}{$key} = $value;
582            }
583        }
584
585
586        # reading from file; more temps
587        while ( <> ) {
588            next unless s/^(.*?):\s*//;
589            my $who = $1;
590            my $rec = {};
591            $HoH{$who} = $rec;
592            for my $field ( split ) {
593                my ($key, $value) = split /=/, $field;
594                $rec->{$key} = $value;
595            }
596        }
597
598        # calling a function  that returns a key,value hash
599        for my $group ( "simpsons", "jetsons", "flintstones" ) {
600            $HoH{$group} = { get_family($group) };
601        }
602
603        # likewise, but using temps
604        for my $group ( "simpsons", "jetsons", "flintstones" ) {
605            my %members = get_family($group);
606            $HoH{$group} = { %members };
607        }
608
609        # append new members to an existing family
610        my %new_folks = (
611            wife => "wilma",
612            pet  => "dino",
613        );
614
615        for my $what (keys %new_folks) {
616            $HoH{flintstones}{$what} = $new_folks{$what};
617        }
618
619   Access and Printing of a HASH OF HASHES
620        # one element
621        $HoH{flintstones}{wife} = "wilma";
622
623        # another element
624        $HoH{simpsons}{lead} =~ s/(\w)/\u$1/;
625
626        # print the whole thing
627        foreach my $family ( keys %HoH ) {
628            print "$family: { ";
629            for my $role ( keys $HoH{$family}->%* ) {
630                print "$role=$HoH{$family}{$role} ";
631            }
632            print "}\n";
633        }
634
635        # print the whole thing  somewhat sorted
636        foreach my $family ( sort keys %HoH ) {
637            print "$family: { ";
638            for my $role ( sort keys $HoH{$family}->%* ) {
639                print "$role=$HoH{$family}{$role} ";
640            }
641            print "}\n";
642        }
643
644
645        # print the whole thing sorted by number of members
646        foreach my $family ( sort { $HoH{$b}->%* <=> $HoH{$a}->%* } keys %HoH ) {
647            print "$family: { ";
648            for my $role ( sort keys $HoH{$family}->%* ) {
649                print "$role=$HoH{$family}{$role} ";
650            }
651            print "}\n";
652        }
653
654        # establish a sort order (rank) for each role
655        my $i = 0;
656        my %rank;
657        for ( qw(lead wife son daughter pal pet) ) { $rank{$_} = ++$i }
658
659        # now print the whole thing sorted by number of members
660        foreach my $family ( sort { $HoH{$b}->%* <=> $HoH{$a}->%* } keys %HoH ) {
661            print "$family: { ";
662            # and print these according to rank order
663            for my $role ( sort { $rank{$a} <=> $rank{$b} }
664                                                      keys $HoH{$family}->%* )
665            {
666                print "$role=$HoH{$family}{$role} ";
667            }
668            print "}\n";
669        }
670

MORE ELABORATE RECORDS

672   Declaration of MORE ELABORATE RECORDS
673       Here's a sample showing how to create and use a record whose fields are
674       of many different sorts:
675
676            my $rec = {
677                TEXT      => $string,
678                SEQUENCE  => [ @old_values ],
679                LOOKUP    => { %some_table },
680                THATCODE  => \&some_function,
681                THISCODE  => sub { $_[0] ** $_[1] },
682                HANDLE    => \*STDOUT,
683            };
684
685            print $rec->{TEXT};
686
687            print $rec->{SEQUENCE}[0];
688            my $last = pop $rec->{SEQUENCE}->@*;
689
690            print $rec->{LOOKUP}{"key"};
691            my ($first_k, $first_v) = each $rec->{LOOKUP}->%*;
692
693            my $answer = $rec->{THATCODE}->($arg);
694            $answer = $rec->{THISCODE}->($arg1, $arg2);
695
696            # careful of extra block braces on fh ref
697            print { $rec->{HANDLE} } "a string\n";
698
699            use FileHandle;
700            $rec->{HANDLE}->autoflush(1);
701            $rec->{HANDLE}->print(" a string\n");
702
703   Declaration of a HASH OF COMPLEX RECORDS
704            my %TV = (
705               flintstones => {
706                   series   => "flintstones",
707                   nights   => [ qw(monday thursday friday) ],
708                   members  => [
709                       { name => "fred",    role => "lead", age  => 36, },
710                       { name => "wilma",   role => "wife", age  => 31, },
711                       { name => "pebbles", role => "kid",  age  =>  4, },
712                   ],
713               },
714
715               jetsons     => {
716                   series   => "jetsons",
717                   nights   => [ qw(wednesday saturday) ],
718                   members  => [
719                       { name => "george",  role => "lead", age  => 41, },
720                       { name => "jane",    role => "wife", age  => 39, },
721                       { name => "elroy",   role => "kid",  age  =>  9, },
722                   ],
723                },
724
725               simpsons    => {
726                   series   => "simpsons",
727                   nights   => [ qw(monday) ],
728                   members  => [
729                       { name => "homer", role => "lead", age  => 34, },
730                       { name => "marge", role => "wife", age => 37, },
731                       { name => "bart",  role => "kid",  age  =>  11, },
732                   ],
733                },
734             );
735
736   Generation of a HASH OF COMPLEX RECORDS
737            # reading from file
738            # this is most easily done by having the file itself be
739            # in the raw data format as shown above.  perl is happy
740            # to parse complex data structures if declared as data, so
741            # sometimes it's easiest to do that
742
743            # here's a piece by piece build up
744            my $rec = {};
745            $rec->{series} = "flintstones";
746            $rec->{nights} = [ find_days() ];
747
748            my @members = ();
749            # assume this file in field=value syntax
750            while (<>) {
751                my %fields = split /[\s=]+/;
752                push @members, { %fields };
753            }
754            $rec->{members} = [ @members ];
755
756            # now remember the whole thing
757            $TV{ $rec->{series} } = $rec;
758
759            ###########################################################
760            # now, you might want to make interesting extra fields that
761            # include pointers back into the same data structure so if
762            # change one piece, it changes everywhere, like for example
763            # if you wanted a {kids} field that was a reference
764            # to an array of the kids' records without having duplicate
765            # records and thus update problems.
766            ###########################################################
767            foreach my $family (keys %TV) {
768                my $rec = $TV{$family}; # temp pointer
769                my @kids = ();
770                for my $person ( $rec->{members}->@* ) {
771                    if ($person->{role} =~ /kid|son|daughter/) {
772                        push @kids, $person;
773                    }
774                }
775                # REMEMBER: $rec and $TV{$family} point to same data!!
776                $rec->{kids} = [ @kids ];
777            }
778
779            # you copied the array, but the array itself contains pointers
780            # to uncopied objects. this means that if you make bart get
781            # older via
782
783            $TV{simpsons}{kids}[0]{age}++;
784
785            # then this would also change in
786            print $TV{simpsons}{members}[2]{age};
787
788            # because $TV{simpsons}{kids}[0] and $TV{simpsons}{members}[2]
789            # both point to the same underlying anonymous hash table
790
791            # print the whole thing
792            foreach my $family ( keys %TV ) {
793                print "the $family";
794                print " is on during $TV{$family}{nights}->@*\n";
795                print "its members are:\n";
796                for my $who ( $TV{$family}{members}->@* ) {
797                    print " $who->{name} ($who->{role}), age $who->{age}\n";
798                }
799                print "it turns out that $TV{$family}{lead} has ";
800                print scalar ( $TV{$family}{kids}->@* ), " kids named ";
801                print join (", ", map { $_->{name} } $TV{$family}{kids}->@* );
802                print "\n";
803            }
804

Database Ties

806       You cannot easily tie a multilevel data structure (such as a hash of
807       hashes) to a dbm file.  The first problem is that all but GDBM and
808       Berkeley DB have size limitations, but beyond that, you also have
809       problems with how references are to be represented on disk.  One
810       experimental module that does partially attempt to address this need is
811       the MLDBM module.  Check your nearest CPAN site as described in
812       perlmodlib for source code to MLDBM.
813

SEE ALSO

815       perlref, perllol, perldata, perlobj
816

AUTHOR

818       Tom Christiansen <tchrist@perl.com>
819
820
821
822perl v5.38.2                      2023-11-30                        PERLDSC(1)
Impressum