Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Hash ordering

by solocazzimiei (Novice)
on Apr 13, 2020 at 22:57 UTC ( #11115490=perlquestion: print w/replies, xml ) Need Help??

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

Hi, is any body explain why an hash content like this:

{'ADR;HOME;ENCODING=QUOTED-PRINTABLE'}: ADR;HOME;ENCODING=QUOTED-PRINT +ABLE {'N;CHARSET=UTF-8'}: N;CHARSET=UTF-8 {'TEL;ASSISTANT'}: TEL;ASSISTANT {'FN;CHARSET=UTF-8'}: FN;CHARSET=UTF-8 {'TEL;HOME'}: TEL;HOME {'TEL;FAX;HOME'}: TEL;FAX;HOME {'TEL;CALLBACK'}: TEL;CALLBACK {'VERSION'}: VERSION {'EMAIL;WORK;PREF;ENCODING=QUOTED-PRINTABLE'}: EMAIL;WORK;PREF;ENCODIN +G=QUOTED-PRINTABLE {'TEL'}: TEL {'TEL;CELL;PREF'}: TEL;CELL;PREF {'N'}: N {'ADR;HOME;CHARSET=UTF-8'}: ADR;HOME;CHARSET=UTF-8 {'TITLE;CHARSET=UTF-8'}: TITLE;CHARSET=UTF-8 {'NOTE;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8'}: NOTE;ENCODING=QUOTED +-PRINTABLE;CHARSET=UTF-8 {'TEL;PAGER'}: TEL;PAGER {'TEL;WORK'}: TEL;WORK {'TEL;CELL'}: TEL;CELL {'TEL;FAX;WORK'}: TEL;FAX;WORK {'NOTE'}: NOTE {'X-ACCOUNT'}: X-ACCOUNT {'TEL;MAIN'}: TEL;MAIN {'BEGIN'}: BEGIN {'TEL;RADIO'}: TEL;RADIO {'EMAIL;LABEL=Pec;PREF'}: EMAIL;LABEL=Pec;PREF {'CATEGORIES'}: CATEGORIES {'TEL;ISDN'}: TEL;ISDN {'BEGIN'}: BEGIN {'ORG'}: ORG {'ADR;WORK;CHARSET=UTF-8'}: ADR;WORK;CHARSET=UTF-8 {'EMAIL;LABEL=Casa;PREF'}: EMAIL;LABEL=Casa;PREF {'ORG;CHARSET=UTF-8'}: ORG;CHARSET=UTF-8 {'TEL;TTY'}: TEL;TTY {'FN'}: FN {'EMAIL'}: EMAIL {'EMAIL;PREF;CHARSET=UTF-8'}: EMAIL;PREF;CHARSET=UTF-8 {'EMAIL;WORK'}: EMAIL;WORK {'TITLE'}: TITLE {'URL'}: URL {'EMAIL;HOME;CHARSET=UTF-8'}: EMAIL;HOME;CHARSET=UTF-8 {'EMAIL;WORK;PREF'}: EMAIL;WORK;PREF {'TEL;LABEL=Cellulare'}: TEL;LABEL=Cellulare {'EMAIL;PREF'}: EMAIL;PREF {'TEL;FAX;OTHER'}: TEL;FAX;OTHER {'TEL;COMPANY'}: TEL;COMPANY {'X-ANNIVERSARY'}: X-ANNIVERSARY {'ADR;WORK;ENCODING=QUOTED-PRINTABLE'}: ADR;WORK;ENCODING=QUOTED-PRINT +ABLE {'ADR;HOME;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8'}: ADR;HOME;ENCODIN +G=QUOTED-PRINTABLE;CHARSET=UTF-8 {'EMAIL;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8'}: EMAIL +;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8 {'ADR;WORK'}: ADR;WORK {'NICKNAME'}: NICKNAME {'ADR;WORK;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8'}: ADR;WORK;ENCODIN +G=QUOTED-PRINTABLE;CHARSET=UTF-8 {'TEL;LABEL=Ufficio'}: TEL;LABEL=Ufficio {'TEL;CELL;WORK'}: TEL;CELL;WORK {'EMAIL;HOME;PREF'}: EMAIL;HOME;PREF {'NOTE;ENCODING=QUOTED-PRINTABLE'}: NOTE;ENCODING=QUOTED-PRINTABLE {'ADR;HOME'}: ADR;HOME {'BDAY'}: BDAY {'TEL;CAR'}: TEL;CAR {'END'}: END

with

%key = sort keys %key;

I'll obtain a shuffled and shorted hash :

{'FN;CHARSET=UTF-8'}: N {'TEL;MAIN'}: TEL;PAGER {'EMAIL;LABEL=Pec;PREF'}: EMAIL;PREF {'CATEGORIES'}: EMAIL {'EMAIL;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8'}: EMAIL +;HOME;CHARSET=UTF-8 {'END'}: FN {'TITLE;CHARSET=UTF-8'}: URL {'TEL;HOME'}: TEL;ISDN {'ADR;HOME'}: ADR;HOME;CHARSET=UTF-8 {'ADR;WORK'}: ADR;WORK;CHARSET=UTF-8 {'TEL;RADIO'}: TEL;TTY {'BDAY'}: BEGIN {'VERSION'}: X-ACCOUNT {'ADR;WORK;ENCODING=QUOTED-PRINTABLE'}: ADR;WORK;ENCODING=QUOTED-PRINT +ABLE;CHARSET=UTF-8 {'TEL;CAR'}: TEL;CELL {'EMAIL;PREF;CHARSET=UTF-8'}: EMAIL;WORK {'N;CHARSET=UTF-8'}: NICKNAME {'ADR;HOME;ENCODING=QUOTED-PRINTABLE'}: ADR;HOME;ENCODING=QUOTED-PRINT +ABLE;CHARSET=UTF-8 {'TEL;WORK'}: TITLE {'EMAIL;WORK;PREF'}: EMAIL;WORK;PREF;ENCODING=QUOTED-PRINTABLE {'TEL;COMPANY'}: TEL;FAX;HOME {'ORG;CHARSET=UTF-8'}: TEL {'EMAIL;HOME;PREF'}: EMAIL;LABEL=Casa;PREF {'NOTE'}: NOTE;ENCODING=QUOTED-PRINTABLE {'TEL;ASSISTANT'}: TEL;CALLBACK {'X-ANNIVERSARY'}: BEGIN {'TEL;LABEL=Cellulare'}: TEL;LABEL=Ufficio {'NOTE;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8'}: ORG {'TEL;FAX;OTHER'}: TEL;FAX;WORK {'TEL;CELL;PREF'}: TEL;CELL;WORK

Thanks

Replies are listed 'Best First'.
Re: Hash ordering
by AnomalousMonk (Bishop) on Apr 13, 2020 at 23:17 UTC

    The statement
        %key = sort keys %key;
    takes the keys (not the associated values) of the hash, uselessly sort-s them (because hash key/value pairs have no inherent order beyond their key/value pairing) and assigns the (pseudo)randomly ordered keys only back to the hash. Please see the discussions of keys, values and each in the Perl documentation, and also associative arrays (hashes).

    c:\@Work\Perl\monks>perl -wMstrict -le "my %alphas = ('a' .. 'x'); print qq{@{[ %alphas ]}}; ;; %alphas = sort keys %alphas; print qq{@{[ %alphas ]}}; " w x e f a b m n s t u v c d k l q r g h i j o p e g a c m o u w q s i k


    Give a man a fish:  <%-{-{-{-<

      One nuance that AnomalousMonk is aware of but I wanted to clarify:

      %key = sort keys %key;

      Let's say you start with a hash that looks like this:

      %key = ( foo => 'bar', bazz => 'bump', ping => 'pong', putt => 'pop', );

      The line of code above would capture only the keys (as was mentioned) and would save them only into the hash, so after running that line you would have this:

      %key = ( foo => 'bazz', ping => 'putt', );

      This is because the output of keys will just be foo, bazz, ping, putt, and when you take a flat list like that and store it into a hash, it is interpreted as key/value pairs. So your new hash loses all the values, and makes value out of half of the keys. If there are an odd number of keys, one of the new keys gets undef as its value, too.

      If we were to break the assignment down to steps it would look more like this:

      %key = ( foo => 'bar', bazz => 'bump', ping => 'pong', putt => 'pop', ); my @keys = keys %key; # foo, bazz, ping, putt %key = @keys; foo => bazz, ping => putt

      The sorting, itself is irrelevant because storing things in a hash loses any concept of order.


      Dave

Re: Hash ordering
by dsheroh (Monsignor) on Apr 14, 2020 at 09:40 UTC
    Not only is the order of hash keys random by nature, Perl 5.8.1 introduced changes to ensure that a given hash's keys would come up in a different order on each run of the program for security reasons:
    Mainly due to security reasons, the "random ordering" of hashes has been made even more random. Previously while the order of hash elements from keys(), values(), and each() was essentially random, it was still repeatable. Now, however, the order varies between different runs of Perl.

    Perl has never guaranteed any ordering of the hash keys, and the ordering has already changed several times during the lifetime of Perl 5. Also, the ordering of hash keys has always been, and continues to be, affected by the insertion order.

    - Perl 5.8.1-RC4 release notes, emphasis in original

      Perl 5.8.1 introduced changes to ensure that a given hash's keys would come up in a different order on each run of the program

      In addition, in 5.18 further changes were made. From Hash overhaul:

      By default, two distinct hash variables with identical keys and values may now provide their contents in a different order where it was previously identical. ... the order which keys/values will be returned from functions like keys(), values(), and each() will differ from run to run. ... Further, every hash has its own iteration order, which should make it much more difficult to determine what the current hash seed is.
Re: Hash ordering
by haukex (Bishop) on Apr 14, 2020 at 08:16 UTC

    AnomalousMonk already explained the issue, I just wanted to add: what is your goal here? Hashes are by definition unordered, so if you want them to be output in a certain way, you'd have to explain what that is. For example, if you just wanted to output the hash with the keys sorted, one of the most common ways to do so is for my $key (sort keys %hash) { ... }, and then access each value inside the loop via $hash{$key}.

Re: Hash ordering
by AnomalousMonk (Bishop) on Apr 13, 2020 at 23:01 UTC

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (2)
As of 2021-05-18 14:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Perl 7 will be out ...





    Results (180 votes). Check out past polls.

    Notices?