0

I have a code as below

@array = qw(Sam London George Washington Luke Shanghai);
my %where = @array;
my @d = keys %where;
my @c = values %where;

print "4. keys - @d values - @c \n";

I am getting

4. keys - George Luke Sam values - Washington Shanghai London

I should be getting 4. keys - Sam George Luke values - London Washington Shanghai

Then I have

my ($a) = %where;
my $b = %where;
my $c = $b + 1;
print "6. $a $b $c \n"

Why am I getting

6. George 2/8 3

So, firstly why am I getting incorrect order when I change array to hash. Secondly, how do I get 2/8 and 3. Instead I am expecting 6 and 7, since there are 6 elements in the hash (3 hash and 3 keys).

2 Answers2

4

Hash does not guarantee to store keys and values in any particular order. That's why @d and @c are in an order you don't expect them to be.

2/8 is what the hash is evaluated to in scalar context. This is explained here: https://stackoverflow.com/a/7428025/4295017. The following reply gives a relevant cite from perldata.

The 2/8 value is stored in $b as string. When evaluated in integer context (imposed by $b + 1 operation) this string value gets converted to 2. That's why $c is 3.

Community
  • 1
  • 1
Dmitry Egorov
  • 9,542
  • 3
  • 22
  • 40
2

First, hashes have no order to rely on, to say the least. From keys

Hash entries are returned in an apparently random order. The actual random order is specific to a given hash; the exact same series of operations on two hashes may result in a different order for each hash.   [ ... ]

This is done on purpose, see the reason in perlsec. You can sort them to print or assign though.

The other problem is due to using a hash in the scalar context. From perldata

If you evaluate a hash in scalar context, it returns false if the hash is empty. If there are any key/value pairs, it returns true; more precisely, the value returned is a string consisting of the number of used buckets and the number of allocated buckets, separated by a slash.

The rest of that documentation passage explains it further.

If you want the number of pairs assign keys %h to a scalar, or use scalar on it.

zdim
  • 64,580
  • 5
  • 52
  • 81