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

Dear Monks!, I have the following hash, my %hash = ( 1 => 'a', 2 => 'b', 3 => 'c', 4 => 'd', 3 => 'e', 6 => 'f', 3 => 'a', 8 => 'b', 1 => 'c', ); When I print the hash using "print reverse %hash", it prints, " b2a3c1d4f6b8 ". What I expect is, the hash won't print duplicate value. ( b is a duplicate ). Probably the return value from reverse function do some magic. Please clarify me. When I use each function in while or using Dumper, it prints correctly. Also I believe, the hash will print the value in the same order (not random and not sort by default). Whenever I print the hash (any hash), the values are printing in the same order. So please give what way the hash is printing.

Replies are listed 'Best First'.
Re: Hash value
by CountZero (Bishop) on Feb 10, 2009 at 11:13 UTC
    Only the keys of a hash must be unique. Its values may repeat.

    Printing the reverse of a hash does not reverse keys and values in the hash. For that to happen you must re-assign the reversed data back to the hash:

    %hash = reverse %hash;
    The order in which a hash "prints" (or the order of the result of the keys, values or each function) is not random but determined by the internal hashing algorithm. For security reasons the order is likely to change between executions of your script although it is guaranteed to be the same order within one run of your script on the same (unmodified) hash.

    So you cannot easily predict the order. If you need the keys (or values) ordered, the best way is to use sort.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      ... or, if you _do_ need predictable ordering (as the order the key-value pairs were entered), use Tie::IxHash

      A user level that continues to overstate my experience :-))
Re: Hash value
by moritz (Cardinal) on Feb 10, 2009 at 10:50 UTC
    A hash in list context is just an even-sized list, so reverse %hash is also just a list. If you want to remove duplicates, you have to assign the result to an array again.
Re: Hash value
by AnomalousMonk (Archbishop) on Feb 10, 2009 at 11:17 UTC
    What I expect is, the hash won't print duplicate value. ( b is a duplicate ).
    Hashes do not have duplicate keys; hash values may be any scalar, duplicated or not.

    Also I believe, the hash will print the value in the same order (not random and not sort by default).
    The 'order' of keys or values in a hash varies from run to run of a Perl script. See the section on Algorithmic Complexity Attacks in perlsec. Also see the discussion on apparent order in the docs for keys, values and each (the paragraph is the same in each case).
Re: Hash value
by Anonymous Monk on Feb 10, 2009 at 12:10 UTC