views:

646

answers:

8

Can someone suggest a good module in perl which can be used to store collection of objects?

Or is ARRAY a good enough substitute for most of the needs?

Update: I am looking for a collections class because I want to be able to do an operation like compute collection level property from each element.

Since I need to perform many such operations, I might as well write a class which can be extended by individual objects. This class will obviously work with arrays (or may be hashes).

A: 

i would stick with an ARRAY or a HASH.

 @names = ('Paul','Michael','Jessica','Megan');

and

my %petsounds = ("cat" => "meow",
             "dog" => "woof",
             "snake" => "hiss");

source

ethyreal
+1  A: 

Base your decision on how you need to access the objects. If pushing them onto an array, indexing into, popping/shifting them off works, then use an array. Otherwise hash them by some key or organize them into a tree of objects that meets your needs. A hash of objects is a very simple, powerful, and highly-optimized way of doing things in Perl.

andy
+2  A: 

I would normally use an @array or a %hash.

What features are you looking for that aren't provided by those?

cjm
+1  A: 

Since Perl arrays can easily be appended to, resized, sorted, etc., they are good enough for most "collection" needs. In cases where you need something more advanced, a hash will generally do. I wouldn't recommend that you go looking for a collection module until you actually need it.

Derek Park
A: 

Either an array or a hash can store a collection of objects. A class might be better if you want to work with the class in certain ways but you'd have to tell us what those ways are before we could make any good recommendations.

Michael Carman
+4  A: 

There are collection modules for more complex structures, but it is common style in Perl to use Arrays for arrays, stacks and lists. Perl has built in functions for using the array as a stack or list : push/pop, shift/unshift, splice (inserting or removing in the middle) and the foreach form for iteration.

Perl also has a map, called a hashmap which is the equivalent to a Dictionary in Python - allowing you to have an association between a single key and a single value.

Perl developers often compose these two data-structures to build what they need - need multiple values? Store array-references in the value part of the hashtable (Map). Trees can be built in a similar manner - if you need unique keys, use multiple-levels of hashmaps, or if you don't use nested array references.

These two primitive collection types in Perl don't have an Object Oriented api, but they still are collections.

If you look on CPAN you'll likely find modules that provide other Object Oriented data structures, it really depends on your need. Is there a particular data structure you need besides a List, Stack or Map? You might get a more precise answer (eg a specific module) if you're asking about a particular data structure.

Forgot to mention, if you're looking for small code examples across a variety of languages, PLEAC (Programming Language Examples Alike Cookbook) is a decent resource.

Kyle Burton
Perl uses the term "hash," not "hashmap" or "hashtable." Please *don't* use "map" as that's the name of a built-in function for list manipulation.
Michael Carman
A: 

It depends a lot; there's Sparse Matrix modules, some forms of persistence, a new style of OO etc Most people just man perldata, perllol, perldsc to answer their specific issue with a data structure.

dlamblin
+3  A: 

I would second Michael Carman's comment: please do not use the term "Hashmap" or "map" when you mean a hash or associative array. Especially when Perl has a map function; that just confuses things.

Having said that, Kyle Burton's response is fundamentally sound: either a hash or an array, or a complex structure composed of a mixture of the two, is usually enough. Perl groks OO, but doesn't enforce it; chances are that a loosely-defined data structure may be good enough for what you need.

Failing that, please define more exactly what you mean by "compute collection level property from each element". And bear in mind that Perl has keywords like map and grep that let you do functional programming things like e.g.

my $record = get_complex_structure();
# $record = {
#    'widgets' => {
#        name => 'ACME Widgets',
#        skus => [ 'WIDG01', 'WIDG02', 'WIDG03' ],
#        sales => {
#            WIDG01 => { num => 25, value => 105.24 },
#            WIDG02 => { num => 10, value => 80.02 },
#            WIDG03 => { num => 8,  value => 205.80 },
#        },
#    },
#    ### and so on for 'grommets', 'nuts', 'bolts' etc.
# }

my @standouts =
    map { $_->[0] }
    sort {
        $b->[2] <=> $a->[2] 
     || $b->[1] <=> $a->[1]
     || $record->{$a->[0]}->{name} cmp $record->{$b->[0]}->{name}
    }
    map {
        my ($num, $value);
        for my $sku (@{$record->{$_}{skus}}) {
            $num   += $record->{$_}{sales}{$sku}{num};
            $value += $record->{$_}{sales}{$sku}{value};
        }
        [ $_, $num, $value ];
    }
    keys %$record;

Reading from back to front, this particular Schwarztian transform does three things:

3) It takes a key to $record, goes through the SKUs defined in this arbitrary structure, and works out the aggregate number and total value of transactions. It returns an anonymous array containing the key, the number of transactions and the total value.

2) The next block takes in a number of arrayrefs and sorts them a) first of all by comparing the total value, numerically, in descending orders; b) if the values are equal, by comparing the number of transactions, numerically in descending order; and c) if that fails, by sorting asciibetically on the name associated with this order.

1) Finally, we take the key to $record from the sorted data structure, and return that.

It may well be that you don't need to set up a separate class to do what you want.

Sam Kington