[Golf-ish] Ordered hash keys

D

Damian James

Hi folks,

So I wanted to define a lookup table that I would later need to
iterate over in a specific order. That's easy enough, there are
many ways to do it; but I specifically wanted to keep the neat,
visually oriented table in my code:

my @mappings = (
field1 => 'otherLongwindedDirectoryAttribute',
field2 => 'kitchenSink',
field3 => 'userDistanceBetweenEyes'
);
my %lookup = @mappings;
my @fields = @mappings[ map $_*2, 0..($#mappings/2) ];

....where obviously I am only interested in %lookup and @fields, but
want to keep the table in the interests of easy alteration.

So how might I avoid defining @mappings? Is there a simpler, shorter
or more elegant 'hashificator' that might be suitable in place of the
arithmetic one I've shown? People maintaining this later may well not
be able to find their own um, keyboard, with detailed directions and
a map, but just might be able to change a lookup table if it's clear
enough and the instructions are sufficiently detailed.

I know I can:

my %lookup;
@lookup{ my @fields = qw/field1 field2 field3/ } =
qw/other kitch user/;

But that sacrifices the vertical orientation, and that just won't fit
neatly with the rather long directory attribute names.

This is obviously a style question more than anything, so the more
playful the suggestions the better I guess ;).

--damian
 
F

Fabian Pilkowski

* Damian James said:
So I wanted to define a lookup table that I would later need to
iterate over in a specific order. That's easy enough, there are
many ways to do it; but I specifically wanted to keep the neat,
visually oriented table in my code:

my @mappings = (
field1 => 'otherLongwindedDirectoryAttribute',
field2 => 'kitchenSink',
field3 => 'userDistanceBetweenEyes'
);
my %lookup = @mappings;
my @fields = @mappings[ map $_*2, 0..($#mappings/2) ];

...where obviously I am only interested in %lookup and @fields, but
want to keep the table in the interests of easy alteration.

When typing `perldoc -q "keep my hash sorted"` I get:

Found in C:\Programme\Perl\lib\pod\perlfaq4.pod
How can I always keep my hash sorted?
You can look into using the DB_File module and tie() using the $DB_BTREE
hash bindings as documented in "In Memory Databases" in DB_File. The
Tie::IxHash module from CPAN might also be instructive.

Have a look at this Tie::IxHash from CPAN. Your code could look like:


use Tie::IxHash;
tie( my %lookup, 'Tie::IxHash',
field1 => 'otherLongwindedDirectoryAttribute',
field2 => 'kitchenSink',
field3 => 'userDistanceBetweenEyes'
);
my @fields = keys %lookup;


But I think you don't need your array @fields anymore when using this
module. When keep sorted your Hash by another value have a look at
Tie::Hash::Sorted. In the past many people have thought about ordered
hashes -- I think you won't reinventing the wheel ... ;-)

regards,
fabian
 
T

Tad McClellan

Damian James said:
my @fields = @mappings[ map $_*2, 0..($#mappings/2) ];
Is there a simpler, shorter
or more elegant 'hashificator' that might be suitable in place of the
arithmetic one I've shown?


You can save 3 strokes by generating the slice indexes with:

grep $_%2, 0..$#mappings

instead of map().
 
P

Peter Wyzl

: Hi folks,
:
: So I wanted to define a lookup table that I would later need to
: iterate over in a specific order. That's easy enough, there are
: many ways to do it; but I specifically wanted to keep the neat,
: visually oriented table in my code:
:
: my @mappings = (
: field1 => 'otherLongwindedDirectoryAttribute',
: field2 => 'kitchenSink',
: field3 => 'userDistanceBetweenEyes'
: );
: my %lookup = @mappings;
: my @fields = @mappings[ map $_*2, 0..($#mappings/2) ];
:
: ...where obviously I am only interested in %lookup and @fields, but
: want to keep the table in the interests of easy alteration.


I have previously done somthing like:

my %lookup = (
field1 => 'otherLongwindedDirectoryAttribute',
field2 => 'kitchenSink',
field3 => 'userDistanceBetweenEyes'
);

my @fields = sort(keys(%lookup));

But this relies on sort giving you the order you want rather than a specific
order which may not necessarily match sort's output. Unless you can define
some sort routine that matches your preferred order. In the example given
it would match but that is probably just a happy coincidence of your example
data. How critical is the 'preferred order' of the keys compared to a
'sorted order' of the keys for later processing?

P
 
A

Anno Siegel

Tad McClellan said:
Damian James said:
my @fields = @mappings[ map $_*2, 0..($#mappings/2) ];
Is there a simpler, shorter
or more elegant 'hashificator' that might be suitable in place of the
arithmetic one I've shown?


You can save 3 strokes by generating the slice indexes with:

grep $_%2, 0..$#mappings

instead of map().

Yes, but that selects odd elements, not even ones.

Anno
 
B

Bart Lateur

Fabian said:
When typing `perldoc -q "keep my hash sorted"` I get:

Found in C:\Programme\Perl\lib\pod\perlfaq4.pod
How can I always keep my hash sorted?
You can look into using the DB_File module and tie() using the $DB_BTREE
hash bindings as documented in "In Memory Databases" in DB_File. The
Tie::IxHash module from CPAN might also be instructive.

Have a look at this Tie::IxHash from CPAN.

See also Tie::Hash::Indexed, which is an XS implementation.

<http://search.cpan.org/search?module=Tie::Hash::Indexed>


I wish module authors chose their names so it's more obvious what other
modules they're related to.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top