I have this associative array in a little Perl program that does something very weird:
#!/usr/bin/perl
use utf8;
use strict;
use warnings;
use open qw(:utf8 :std);
my %distancia = (
esto => 1,
eso => 10,
aquello => 100,
aquí => 1,
ahí => 10,
allí => 100,
);
for my $clave (keys %distancia) {
my $valor = $distancia{$clave};
printf "%-8s es %3d.\n", $clave, $valor;
}
Every time I print it, it randomly changes the order:
mac(tchrist)% perl matriz-asociativa
esto es 1.
aquello es 100.
eso es 10.
allí es 100.
ahí es 10.
aquí es 1.
mac(tchrist)% perl matriz-asociativa
eso es 10.
ahí es 10.
aquí es 1.
esto es 1.
aquello es 100.
allí es 100.
mac(tchrist)% perl matriz-asociativa
allí es 100.
aquí es 1.
ahí es 10.
eso es 10.
esto es 1.
aquello es 100.
mac(tchrist)% perl matriz-asociativa
aquello es 100.
aquí es 1.
allí es 100.
esto es 1.
eso es 10.
ahí es 10.
mac(tchrist)% perl matriz-asociativa
ahí es 10.
aquí es 1.
eso es 10.
aquello es 100.
allí es 100.
esto es 1.
What is happening to me here, and what should I do to get a certain order every time?
If it matters, it says that the version of perl I have is v5.22.0 :
mac(tchrist)% perl -v
This is perl 5, version 22, subversion 0 (v5.22.0) built for darwin-2level
Copyright 1987-2015, Larry Wall
Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.
Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.
There is an error in what you write: Change the order every time you run the program, not every time you print the associative array.
The associative array is actually not an associative array, but a HashTable . The order is given by the hash used as an index, so in each execution the order is totally different.
If you print the same hash table twice in the same program, you will see that its order is not altered.
The order of a hash table can also be altered in the event that elements are added or removed, since if there are collisions the table has to be modified.
So, in a program you will always have the hash ordered in the same way.
If you want to get the sorted hash every time, you'll have to sort it yourself.
For example, the following code sorts the keys alphabetically, and displays them on the screen.
Edit
Since Perl 5.8, the hash function used to obtain the hash of each inserted key-value pair has had a random seed added for security reasons (to prevent [algorithmic complexity attacks]).
A hash table is a data structure with which it is intended to achieve rapid access to data, based on a key.
There is a series of attacks, known as algorithmic complexity attacks, which consist of causing a part of a program's code to start working in a lousy performance regime. With this, it is possible to carry out a denial of service (DoS), and deprive the rest of the users of a service of access to that service.
To prevent these attacks, a number of measures are used, such as adding a random input to the hash function used. As a side effect, this causes the key order of the hash function to be non-deterministic.
To achieve a deterministic order, it would suffice to order the keys:
Of course, if you want true alphabetical ordering, you'll have to use an alphabetical sorting algorithm, such as UCA, which is available in Perl as
Unicode::Collate::Locale
.