Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Print a hash in order

by Anonymous Monk
on Feb 15, 2006 at 15:06 UTC ( #530400=perlquestion: print w/replies, xml ) Need Help??

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

Hiya,

This is probably quite simple but I can't figure out why it does it...

I basically want to print the key-value pairs in the order they are written, but for some reason this does not happen.

%permissions = ('ATM_NO' => 'No access to ATMs', 'ATM_R' => 'Read ATMs', 'ATM_W' => 'Write ATMs', 'ATM_M' => 'Modify ATMs', 'ATM_D' => 'Delete ATMs', 'ETM_NO' => 'No access to ETMs', 'ETM_R' => 'Read ETMs', 'ETM_W' => 'Write ETMs', 'ETM_M' => 'Modify ETMs', 'ETM_D' => 'Delete ETMs' ); while (($perm_name, $perm_desc) = each(%permissions)) { print "\nINSERT INTO permissions SET name='$perm_name', descriptio +n='$perm_desc'\n"; }
prints out...
INSERT INTO permissions SET name='ATM_D', description='Delete ATMs' INSERT INTO permissions SET name='ATM_W', description='Write ATMs' INSERT INTO permissions SET name='ATM_M', description='Modify ATMs' INSERT INTO permissions SET name='ETM_W', description='Write ETMs' INSERT INTO permissions SET name='ETM_D', description='Delete ETMs' INSERT INTO permissions SET name='ATM_NO', description='No access to A +TMs' INSERT INTO permissions SET name='ATM_R', description='Read ATMs' INSERT INTO permissions SET name='ETM_NO', description='No access to E +TMs' INSERT INTO permissions SET name='ETM_M', description='Modify ETMs' INSERT INTO permissions SET name='ETM_R', description='Read ETMs'
Why is it in that order? It doesnt appear to be related to the values or alphabetical in any way, it also seems to be consistent across other hashes as well. Sorting them will not work as an order different to the one written will be generated, does anyone have any ideas?

Thanks for your time, dalton

Replies are listed 'Best First'.
Re: Print a hash in order
by McDarren (Abbot) on Feb 15, 2006 at 15:17 UTC
    If you need to preserve the insertion order, then you probably want Tie::IxHash

    Cheers,
    Darren :)

Re: Print a hash in order
by radiantmatrix (Parson) on Feb 15, 2006 at 16:01 UTC

    Well, you could read the perlfaq question How can I make my hash remember the order I put elements into it ?

    Or, if your case is as simple as you've laid out, you could avoid the hash altogether:

    # arrays preserve order. => will be treated as a comma @permissions = ('ATM_NO' => 'No access to ATMs', 'ATM_R' => 'Read ATMs', 'ATM_W' => 'Write ATMs', 'ATM_M' => 'Modify ATMs', 'ATM_D' => 'Delete ATMs', 'ETM_NO' => 'No access to ETMs', 'ETM_R' => 'Read ETMs', 'ETM_W' => 'Write ETMs', 'ETM_M' => 'Modify ETMs', 'ETM_D' => 'Delete ETMs' ); my $index = 0; while ($index < $#permissions-1) { ($perm_name, $perm_desc) = @permissions[$index,$index+1]; print "\nINSERT INTO permissions SET name='$perm_name', descriptio +n='$perm_desc'\n"; $index += 2; }

    Updates:

    • 2006-02-15 : Thanks to rinceWind, salva, and wfsp for pointing out that I neglected to increment $index. *blush* It's fixed now.

    <-radiant.matrix->
    A collection of thoughts and links from the minds of geeks
    The Code that can be seen is not the true Code
    I haven't found a problem yet that can't be solved by a well-placed trebuchet
Re: Print a hash in order
by salva (Abbot) on Feb 15, 2006 at 15:28 UTC
    The order of the elements of a hash is undefined. You can use Tie::IxHash for a hash implementation that retains the order of its elements, but usually there are simpler ways to obtain the same result with perl builtins, for instance:
    my @perm_names = qw(ATM_NO ATM_R ATM_W ATM_D ...); my %perms; @perms{@perm_names} = ( 'No access to ATMs', 'Read ATMs', 'Write ATMs', 'Modify ATMs', ... ); for (@perm_names) { print "\nINSERT INTO permissions SET name='$_', description='$perms{ +$_}'\n"; }
Re: Print a hash in order
by bassplayer (Monsignor) on Feb 15, 2006 at 15:13 UTC

    The order that values are entered into a hash are not relevant to how they are later retrieved. You cannot count on the order of hash keys or values. Your best bet is probably to sort on the keys before iterating through them.

    bassplayer

Re: Print a hash in order
by ww (Archbishop) on Feb 15, 2006 at 15:19 UTC
    dalton:
    The order of hash content is arbitrary. This snippet (from perldoc -q Hash) brushes the topic:
    • How do I process an entire hash?
      • Use the each() function (see "each" in perlfunc) if you don't care whether it's sorted:
        while ( ($key, $value) = each %hash) { print "$key = $value\n"; }

        If you want it sorted, you'll have to use foreach() on the result of sorting the keys ...

    HTH, but the real bottom line is -- please read your documentation.

Re: Print a hash in order
by tweetiepooh (Hermit) on Feb 15, 2006 at 15:44 UTC
    As others have pointed out, order in a hash is arbitary in normal usage.

    As it appears you are putting this data into a database why does it matter about the order unless the is some "hidden" sequence that makes it important. The queries used to retrieve that data can sort it for you.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://530400]
Approved by McDarren
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (4)
As of 2020-01-27 05:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?