Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

hi,
Anyone to have idea how can I create a such a structure that act like a 4way-HASH i.e. I can query back and fourth 4-way meta-keys . Example :
the four key-types are : mac, ip, file, name So now I want to be able to say :
print $hash{$name1}{ip};#name->ip conversation print $hash{$ip5}{name};#ip->name print $hash{$mac10}{file};#mac->filename print $hash{$mac}{ip};#mac -> ip
etc.....did u get the idea ... The problem is that it is useless and time consuming to populate such a HASH structure..
I can make a hash based only on one key-type, say "name" and for the rest to use foreach cycles to find a match, but this also seems not as good to me...

ANY IDEA

Replies are listed 'Best First'.
Re: compound structure? 4way-hash
by Aristotle (Chancellor) on Aug 26, 2002 at 12:51 UTC
    That isn't directly possible. You can store the data in an array of hashes and use four hashes with references to the entries.
    my @address; my %by_name = map { ($_->{name}, $_) } @address; my %by_file = map { ($_->{file}, $_) } @address; my %by_mac = map { ($_->{mac}, $_) } @address; my %by_ip = map { ($_->{ip}, $_) } @address; print $by_ip{"1.2.3.4"}{name}, $by_name{foobar}, "\n";
    The drawback of course is that whenever the @address data changes you have to update the index hashes accordingly.

    Makeshifts last the longest.

Re: compound structure? 4way-hash
by fglock (Vicar) on Aug 26, 2002 at 12:39 UTC

    You can use a subroutine:

    get_info(mac=>'0494944545', want=>'file');

    If you really need a hash, transform the subroutine into a hash using "tie".

    $hash{mac_04994994_file};

    (hint) Use split("_") to separate the words. It is much easier than simulating a hash-of-hashes.

Re: compound structure? 4way-hash
by Anonymous Monk on Aug 26, 2002 at 13:39 UTC
    I'm parsing a dhcpd.conf file and expect the number of entires to reach probably 1000 at long turn.. At the moment I don't look so much at speed, but will need it may be !!!
    At the moment there is only one case when I will resolv-all entiries (mac->name)...

    my code up to the moment is :
    ...... sub parse { my $self = shift; #parse the classes my @clases = $$self{_data} =~ /class\s+?"(.+?)"\s+?\{.*?=\s*(.+?)\s*; +/gs; while ($#clases > 0) { $$self{_clases}{pop @clases} = pop @clases; } my @hosts = $$self{_data} =~ / host\s*(.+?)\s*\{.*? filename\s*"(.+?)"\s*;.*? ethernet\s*(.+?)\s*;.*? fixed-address\s*(.+?)\s*; /xgs; while ($#hosts > 0) { my $h = shift @hosts; ($$self{_hosts}{$h}{file}, $$self{_hosts}{$h}{mac}, $$self{_hosts}{$h}{ip}) = splice @hosts,0,3; } } sub name2 { my ($self, $name, $to) = @_; $$self{_hosts}{$name}{$to} } 1;
    One thing on which i would like to hear your comment is the while cycles ... did u see "my $h", if i try this :
    (my $h, $$self{_hosts}{$h}{file}, $$self{_hosts}{$h}{mac}, $$self{_hosts}{$h}{ip}) = splice @hosts,0,4;
    it wont work... not a big deal but it is interesting to know why ?
      How often is this script running? "1000 lines" doesn't say much. If you run it once a day, 1000 lines is a pretty miniscule burden.

      Makeshifts last the longest.

Re: compound structure? 4way-hash
by BrowserUk (Patriarch) on Aug 26, 2002 at 14:06 UTC

    To be really generic, you'd need to add combinations algorithm to generate the 2 from n indices at the top, but 2 from 4 is easier to do by hand.

    #! perl -w use strict; use Data::Dumper; # if the number of fields was to vary you could generate the combinati +ons using an algorithm. my @sets = ( [1,2,3], # 1st (index 0) field can be combined with these othe +r fields. [0,2,3], # 2nd with these... [0,1,3], [0,1,2] ); my %hash; my @labels = split/\s+/, <DATA>; # read the labels from the first l +ine of the DATA... while (<DATA>) { chomp; my @fields = split; for my $index (0 .. $#sets) { $hash{ $labels[$index] }{ $fields[$_] } = $fields[$index] for (@{$sets[$index]}[0 .. 2]); } } print Dumper(\%hash); __DATA__ mac ip name file ABCDEFABCDEF10 10.0.0.1 www.foo1.com afilename1 ABCDEFABCDEF02 10.0.0.2 www.foo2.com afilename2 ABCDEFABCDEF03 10.0.0.3 www.foo3.com afilename3 ABCDEFABCDEF04 10.0.0.4 www.foo4.com afilename4 ABCDEFABCDEF05 10.0.0.5 www.foo5.com afilename5

    When run produces the following output.

Re: compound structure? 4way-hash
by derby (Abbot) on Aug 26, 2002 at 12:32 UTC
    Hmmm ... RDBMS qualities without the database overhead, perhaps some of the "lite" DBD drivers would be helpful: DBD::SQLite or DBD::CSV.

    -derby