I don't think that Perl guarantees that behavior.

In general, hashes are iterated in bucket order, (and Perl does guarentee that values are returned in the same order as keys). Bucket order is a function of the hashing algorithm used which is fixed in Perl. Even with the hash randomisation fix for the "algorithm complexity attack" on Perl's hashes--which changes the initalisation values used by the hashing algorithm, the ordering is guarenteed to remain the same for any given run of the program which is all that is required of the code above.

Essentially, if a hash contains the same keys, keys (and therefore values) will return them in the same order, regardless of the order they were inserted in. This can be demonstrated to be so:

#! perl -sw use 5.010; use strict; use List::Util qw[ shuffle ]; our $I ||= 1e6; sub genHash { my %hash; @hash{ shuffle 'a'..'d' } = 1 .. 4; return \%hash; } my $datum = join ' ', keys %{ genHash() }; warn $datum . "\n"; for my $i ( 1 .. $I ) { my $test = join ' ', keys %{ genHash() }; die "test failed after $i iters: $datum vs. $test\n" unless $datum eq $test; } say "Test passed for $I iterations" __END__ C:\test>junk2 c a b d Test passed for 1000000 iterations

However, there is a caveat to this that obviously did not occur to me back in the day. Whilst the iteration order is independent of the insertion order, it is dependant upon the number of buckets in the hash.

That is, if the hashes being compared contain the same keys--and have never contained any other keys--their iteration orders will be the same. But, if the hashes have different numbers of buckets; if for example, one of them has previously contained more keys some of which have subsequently been deleted; then their iteration orderings will differ:

@hashA{ 'a'..'d' } = 1..4;; @hashB{ 'a'..'j' } = 1 .. 10;; delete $hashB{ $_ } for 'e' .. 'j';; print scalar %hashA;; 4/8 print scalar %hashB;; 4/16 print join ' ', keys %hashA;; c a b d print join ' ', keys %hashB;; a d c b

So, whilst this is unlikely to have affected the OPs application, for general application it would be better to sort the values by key order. As would using a join delimiter that is not going to occur in the values being concatenated:

my $value_key = join $;, @students{ sort keys %{ $students{ $key } } } +;

Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
"Too many [] have been sedated by an oppressive environment of political correctness and risk aversion."

In reply to Re^3: delete duplicate hash value's by BrowserUk
in thread delete duplicate hash value's by juo

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.