Autovivification trick
blazar
created: 2006-08-12 06:02:26
Minimal example exhibiting a double reference autovivification trick (learnt from Brian McCauley in a clpmisc thread) to convert a list of structured strings as that below the __END__ token to a complex data structure as that illustrated by the output of the program. [id://567024|More details] follow.
#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my %dirhash;
while () {
    chomp;
    my $last=\\%dirhash;
    $last=\$$last->{$_} for split qr|/|;
}

print Dumper \%dirhash;

__END__
/file.txt
/a/file.txt
/a/b/c
/a/b/c/file.txt
/z/m/w/file.txt
Re: Autovivification trick
created: 2006-08-12 06:56:58

Some more details: in [href://news:1155102735.358626.78050@i3g2000cwc.googlegroups.com|this post] someone asked how to "take strings like:"

/file.txt
/a/file.txt
/a/b/c
/a/b/c/file.txt
/z/m/w/file.txt

and "produce something like:"

%dir_hash(
    'file.txt' => '',
    'a' => {
        'file.txt' => '',
        'b' => {
            'c' => {
                'file.txt'
[snip]

In [href://news:scdjd21o3tvo6llfh0he2u7lqijk5nbl8o@4ax.com|my reply] I pointed out that there should be a module designed for exactly this kind of things, which I still fail to remember. (Hey, anyone here? Update: It's [mod://Data::Diver], thanks [id://567395|to] [tye]!) But first of all I provided a minimal example to accomplish not exactly the same task, but a very close one; the original code is as follows:

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my %dirhash;
while () {
    chomp;
    my $last=\%dirhash;
    $last=$last->{$_} ||= {} for split qr|/|;
}

print Dumper \%dirhash;

__END__
/file.txt
/a/file.txt
/a/b/c
/a/b/c/file.txt
/z/m/w/file.txt

In it I have to compensate for perl not autovivifying in this case. Then Brian McCauley [href://news:1155126713.054857.300580@m73g2000cwd.googlegroups.com|provided] an alternative way, precisely suggesting that one do

my $last=\\%dirhash;
$last=\$$last->{$_} for split qr|/|;

Instead, which is the [id://567020] I'm "advertising" here.

Re^2: Autovivification trick
created: 2006-08-12 20:11:44

there should be a module designed for exactly this kind of things
The only thing I found (during my admittedly limited search) was Data::Hierarchy - could that have been the one you were thinking of? It appears to be somewhat specialized and may not quite satisfy the same requirements that your snippet does, but it's the closest thing that I found.

Re: Autovivification trick
created: 2006-08-12 15:14:31
You probably read this, I'm not sure there's a module for this.

Update: this post was actually inteded as a reply to Re: Autovivification trick, sorry for mis-clicking.

Flavio
perl -ple'$_=reverse' << Don't fool yourself.

Re^2: Autovivification trick
created: 2006-08-12 15:47:06
You probably read this, I'm not sure there's a module for this.

No, that was not it. Indeed I had never read it. I can't have imagined having seen a module used for this kinda stuff, though. I'm confident I actually did. It must have been just a few days ago.

Re: Autovivification trick
created: 2006-08-13 18:06:19

Thanks for this. In my admittedly limited experience to date, I'd only ever thought of autovivification as a Bad Thing™. Something to be avoided at all costs. How refreshing, in the meantime, to have come across such wonderful and creative counterexamples in nodes such as yours, as well as tlm's "BUG" and injunjoel's RFC: The Uniqueness of hashes. :-)

planetscape
Re: Autovivification trick
created: 2006-08-13 18:52:25

I'm not sure the diminished readabilty brought on by a second level of indirection is worth avoiding the use of ||= {}.

However, its use is localized, so one can understand the function of the code (through comments) without having to understand the trick.

Re: Autovivification trick (old)
tye
created: 2006-08-15 01:23:45

Dog, I was doing that back in 2000. Or you can just use Data::Diver. (:

- tye        

Re^2: Autovivification trick (old)
created: 2006-08-15 05:45:45
Dog, I was doing that back in 2000

Didn't know. Just discovered it. Thought it was interesting enough to deserve an "ad".

Or you can just use Data::Diver. (:

It's exactly the module I was thinking of.

perlmonks.org content © perlmonks.org and blazar, bobf, frodo72, ikegami, planetscape, tye

prlmnks.org © 2006 edmund von der burg (eccles & toad)

v 0.03