http://www.perlmonks.org?node_id=260966

Monks

Further to my ramblings here about creating a hash that has multiple values per key I have gone the whole hog and written an object to perform this function having been advised that no such object currently exists. I don't think that it is comprehensive enough to be placed on CPAN but I do think that it may be useful to other users so I am posting it here.

Example usage and other details are included in the pod docs at the top of the file. Any constructive suggestions greatly appreciated. Code below:

=head1 NAME Datastruct::MultiMap =head1 DESCRIPTION This object provides a simple front to a hash mapping keys to arrays o +f values thus allowing multiple values for a single key. =head1 AUTHOR Arun Horne (arun@simbios.net) =head1 VERSION HISTORY 1.0 - Initial version (27 May 2003) =head1 USAGE use strict; use warnings; use Datastruct::MultiMap; use Data::Dumper; # Create a multimap object my $map = Datastruct::MultiMap->new(); # Add some keys $map->put('K1','V1'); $map->put('K1','V2'); $map->put('K2','V3'); $map->put('K3','V4'); print Dumper $map; # Get values my @values = $map->get('K1'); print Dumper \@values; # Remove keys $map->remove('K1'); print Dumper $map; # Can still access as a normal hash if you want print join(",", sort keys %$map), "\n"; =cut package Datastruct::MultiMap; use strict; use warnings; # # Creates an empty multimap. # sub new() { my $class = shift; my $self = {}; bless $self, $class; return $self; } # # Stores a (key, value) pair into the map # sub put() { my ($self, $key, $value) = @_; unless (exists $self->{$key}) { $self->{$key} = []; } push @{$self->{$key}}, $value; } # # Returns an array of all the values mapped by the specific key # sub get() { my ($self, $key) = @_; return @{$self->{$key}}; } # # Removes all of the values mapped by the specified key. # sub remove() { my ($self, $key) = @_; delete $self->{$key}; } # Package must return true 1;
____________
Arun

Replies are listed 'Best First'.
Re: Object to Map Multiple Values to a Single Key
by broquaint (Abbot) on May 27, 2003 at 12:02 UTC
    A couple of thoughts

    • the subs in your package have prototypes which expect no arguments (although this won't effect them as methods since methods bypass prototypes)
    • you don't need the unless statement in the put method as the hash value will be auto-vivified as an array reference via the push
    • this may be better more naturally realised as a tied interface
    • why wrap an object around a basic data type as it seems to be merely abstracting away dealing with references?

    Apart from the above meanderings it seems fine if that's what you want from your object.
    HTH

    _________
    broquaint

Re: Object to Map Multiple Values to a Single Key
by Abigail-II (Bishop) on May 27, 2003 at 12:30 UTC
    This object provides a simple front to a hash mapping keys to arrays of values thus allowing multiple values for a single key.

    But it uses on OO interface, and hence you are missing out on all of the goodies hashes have to offer. No slices, no keys, no values, no each.

    You are just offering a trivial object to store keys with many values in, not a replacement for hashes.

    Abigail

      Personally I concur with both Abigail-II and jeffa. They have already talked about what they think is not quite right, and I'll add a bit more.

      Not only do we lose yummy hash goodness, but everytime we go to add data via this methodology, or remove data we are copying the entire array contents, allocate more memory, etc.... Granted on smaller data sets this might be trivial, but when the data sets get larger, and the hash structure gets sparser, this will lead to serious performance degredation.

      I have had issues with some of Abigail-II's comments in the past as well, but 9 times out of 10 they are spot on technically, and it's just my ego getting in the way of me learning something new. I think that the whole point of the comments here were really just an attempt to show you that this particular wheel, isn't really a wheel and attempting to reinvent it may lead you to BadPlaces(TM). I would personally be interested to hear/read why you needed this abstraction.

      No offense against your skill level coding, but this smacks of a learning process, looking back over my own personal experience. It feels like you may be making this abstraction to get around some other issue. More of a band-aid as opposed to a diagnosis and treatment. What can you use this as a base for that you couldn't with a normal hash or hash ref? Why a hash instead of an array, with elements you need being assigned numerical values? What problem space are you addressing?

      One last thing. Personally I feel like you turned around and did to Abigail-II exactly what you claimed (he/she?) did to you. Personally I think the right thing to do would be to apologize to (him/her?), even if it isn't public as your comments came across as off the cuff, scathing, and down right immature..

      Note: I'm simply asking you to look at the mirror, not attempting to start a flame war.

      MMMMM... Chocolaty Perl Goodness.....
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Object to Map Multiple Values to a Single Key
by RMGir (Prior) on May 27, 2003 at 12:00 UTC
    Interesting... I think it might be clearer to just use the HoA directly, but that's another "TMTOWTDI"...

    I'm fairly certain you don't need the "unless (exists..." in put. Using "push @{$self->{$key}},$value" will auto-vivify $self->{$key} as an array ref if necessary.
    --
    Mike

•Re: Object to Map Multiple Values to a Single Key
by merlyn (Sage) on May 27, 2003 at 21:09 UTC
    Further to my ramblings here about creating a hash that has multiple values per key I have gone the whole hog and written an object to perform this function having been advised that no such object currently exists.
    No such object currently exists because you are describing a hash-of-arrayrefs, which is a built-in to Perl.

    I concur with the other heavy hitters that have weighed in on this thread already. Your module would never be included in code that I wrote, nor recommended by me in a publication I'm writing or class that I'm teaching. You are abstracting something that in this form does not need abstraction.

    For an extreme example of the absurdity of this approach, check out the Meta hierarchy. Be sure you're sitting down while reading it, and not current swallowing any liquids.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

      A coworker once commented to me that the only explanation she could figure out for Meta was that it was some kind of subtle piece of performance art...