[ABE.pm] Re: Accessing data in an array?

Ricardo SIGNES rjbs-perl-abe at lists.manxome.org
Tue Nov 30 10:45:42 CST 2004


* Faber Fedor <faber at linuxnj.com> [2004-11-30T11:24:17]
> > 
> > This question doesn't seem to make sense to me.  If @indices is an
> > array, you can never dereference it as a hash, as you are doing when you
> > say $indices->{weight}.
> 
> I kinda figured that and that's why I'm asking youse guys. :-)
> 
> > When you say C< for (@indices) > you are getting $_ set, each iteration,
> > to the reference to a hash contained within the next element of the
> > array @indices.
> 
> So this is an array of hashes, right?

Every array is an array of scalars.  The array you created was, too, and
the scalars it contained were references to hashes.  We'd often call
this an "array of hashes" or "list of hashes" (or "LOH") but it's
important that, before you call it by a close-enough name, you know the
actual nature: it's an array of scalars, each of which is a hashref.

> > Do you mean that you need to know the numerical index of the current
> > iteration?  I guess I need you to ask the question differently; maybe
> > give a real-world example?
> 
> What I've been doing is looping through the array and calling functions.
> Because of the code (that I did NOT write), I am passing the value of
> the index to a function.  I need to access the other members of the hash
> for that value.
> 
> The only thing I've thought of so far is this pseudo-code:
> 
> sub returnIndicesValues($) {
>     my ($index) = @_;
> 
>     for(@indices) {
>          return (weight, cap) if $_->{index} eq $index ;
>     }
> }

Don't use prototypes.  They don't do what most people think, and they
end up causing a lot of trouble.  Take it from Tom C, one of the Camel
authors:

	http://library.n0i.net/programming/perl/articles/fm_prototypes/

Also, don't mix tabs and spaces!  Was that really your doing?

So, @incides here is a global, or at least declared in a larger
containing scope?  It looks like what you want to do, there, is return
attributes for the hashref with the given value in a specific key.

My first note would be that you'd be better served by a HOH -- a hash of
hashes or, more properly, a hash in which the values are references to
hashes.

 my %hash = (
 	102 => { volume => 10, weight => 12 },
 	103 => { volume =>  9, weight => 91 },
 	  1 => { volume =>  1, weight =>  1 }
 );

Failing that:

 my @matches = grep { $_->{key} eq $key } @indices;
 return unless @matches; # nothing matched
 die "more than one match!!" if @matches > 1; # too many matches!
 return ($matches[0]{volume}, $matches[0]{weight}); # the only match

Note that I have to handle "more than one match" here, because a LOH
can't enforce uniqueness on the index key.  A HOH could.  I still think
this code is ugly, but it should demonstrate the point.

Also note that I'm calling it "key" instead of "index."  Index is
usually positional, like in an array, but you're looking for an
unordered match, like a hash key.  (Another red flag that you should be
using a HOH!)

> sub foobar($) {

Where "foobar" should be "print_entry" or something?  Don't confuse me
more than regular life already does!

> 
>     my ($index) = @_;
> 
>     my (weight, cap) = returnIndicesValues($index);
> 
>     print "index = $index \t weight = $weight \t cap = $cap\n";
> }
> 
> 
> I just figure there's a nicer, more Perl-ish solution.

 sub display_entry {
   my ($key) = @_;
   return unless my @values = lookup_values_for($key);
   print "key: $key\nvolume: $values[0]\nweight: $values[1]\n";
 }

Personally, I'd just return the hashref from lookup_values_for, so it
returned { key => x, volume => y, weight => z } (well, really I'd use a
HOH, but...):

 sub display_entry {
   my ($key) = @_;
   return unless my $entry = lookup_entry_for($key);
   printf "%10s: %u\n", $_, $entry->{$_} for qw(key volume weight);
 }

-- 
rjbs
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://mail.pm.org/archives/abe-pm/attachments/20041130/2bdd2a0e/attachment.bin


More information about the ABE-pm mailing list