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

Hi guys !

Is there a way to run backwards on a hash (in exactly the opposite order that returned from keys(%hash) for example)?
I know that looping on a hash by:
while (($key, $val) = each(%hash)) { } # or by: foreach (keys(%hash)) { }
will always run on the hash in the same order (not necessarly from the begining as in array, but still in the same order). what I need is a way to run on the hash in the same order but backwards, for example:
# if I have my @arr = keys(%hash); # and @arr is for example: qw(4 7 2 1 9) # I would expect to get somehow @backwardsArr = qw(9 1 2 7 4);
Is there a short way of doing that without having to run on 'keys' from end (with indexes and stuff like that)? BR> Thanks

Hotshot

Replies are listed 'Best First'.
Re: running backwards on a hash
by davorg (Chancellor) on Dec 11, 2001 at 14:21 UTC

    Do you mean something like:

    foreach (reverse keys %hash) { }

    But, you should note that hashes are unordered so you can never guarantee the order that you'll get the keys back.

    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

      But does reversing on the keys of the same hash will always return the same array (reversed to keys) ?

      Hotshot

        As long as you don't change the hash, then all calls to keys (and therefore reverse keys) will return the same list, in the same order. If you modify the hash inbetween calls to keys then anything could happen.

        Blessed Be
        The Pixel

Re: running backwards on a hash
by rob_au (Abbot) on Dec 11, 2001 at 14:39 UTC
    A few comments ...

    Firstly, hash structures by their nature are unordered lists of scalars - There is no intrinsic order to the index keys which are returned via keys or each. It is discussed in the perldata man page that while a hash may be initialised in a particular order it is no guarentee that iteration of the hash index returns elements in this order - This is also discussed in the perlfunc:keys man page.

    If you are wanting a specific order in the hash indices or values returned in a list, you will need to employ the perlfunc:sort function. eg.

    # iterate by sorted list of hash keys foreach my $key (sort keys %hash) { ... } # iterate by sorted list of hash values foreach my $key (sort { $hash{$b} <=> $hash{$a} } keys %hash) { ... }

    If you are wanting to reverse this sorted order of hash keys or values, you simply need to employ the perlfunc:reverse function. eg.

    # iterate by reverse sorted list of hash keys foreach my $key (reverse sort keys %hash) { ... } # iterate by reverse sorted list of hash values foreach my $key (reverse sort { $hash{$b} <=> $hash{$a} } keys %hash) +{ ... }

     

    perl -e 's&&rob@cowsnet.com.au&&&split/[@.]/&&s&.com.&_&&&print'

Re: running backwards on a hash
by jlongino (Parson) on Dec 11, 2001 at 23:12 UTC
    If preserving the order in which the keys are inserted into a hash and getting them back out in the same order is important then you might want to look into the  Tie::IxHash module.

    A search on  Tie::IxHash will turn up many useful posts.

    HTH,

    --Jim

Re: running backwards on a hash
by Maclir (Curate) on Dec 11, 2001 at 20:59 UTC
    My question to you is:
    What significance do you place on a particular ordering of the hash keys?
    As others have stated, there is no particular logic to the sequence that keys(%hash) will return. And while that will remain constant while ever you make no changes to the contents of the hash itself, I certainly don't believe you can rely on them being in "arrival order".

    Maybe what you need to determine first is why you need the values returned in a particular sequence, and you may find that a simple has (key / value) is not the data structure you require. Maybe a "hash of hashe", with the main key being some sequencing value (timestamp, transaction number, and so on), with the inner hash consisting of the values relating to that key.