3
votes

I'm struggling to understand logic behind hashes in Perl. Task is to load file in to hash and assign values to keys which are created using this file.

File contains alphabet with each letter on its own line:

a
b
c
d
e

and etc,. When using array instead of hash, logic is simple: load file into array and then print each element with corresponding number using some counter ($counter++).

But now my question is, how can I read file into my hash, assign automatically generated values and sort it in that way where output is printed like this:

a:1
b:2
c:3

I've tried to first create array and then link it to hash using

%hash = @array

but it makes my hash non-sortable.

3
What sort of 'automatically generated values' do you mean? Just a number like you would get with $counter++? - ASCIIThenANSI
@ASCIIThenANSI Yes, just a simple $counter++ which increases with each line. This $counter also should be a value for keys in my hash which are represented as letter: key -> a, value -> 1, key - > b, value -> 2. - user4839151

3 Answers

4
votes

There are a number of ways to approach this. The most direct would be to load the data into the hash as you read through the file.

my %hash;
while(<>)
{
    chomp;
    $hash{$_} = $.;    #Use the line number as your autogenerated counter.
}

You can also perform simliar logic if you already have a populated array.

for (0..$#array)
{
    $hash{$array[$_]} = $_;
}

Although, if you are in that situation, map is the perlier way of doing things.

%hash = map { $array[$_] => $_ } @array;
2
votes

Think of a hash as a set of pairs (key, value), where the keys must be unique. You want to read the file one line at a time, and add a pair to the hash:

$record = <$file_handle>;
$hash{$record} = $counter++;

Of course, you could read the entire file into an array at once and then assign to your hash. But the solution is not:

@records = <$file_handle>;
%hash = @records;

... as you found out. If you think in terms of (key, value) pairs, you will see that the above is equivalent to:

$hash{a} = 'b';
$hash{c} = 'd';
$hash{e} = 'f';
...

and so on. You still are going to need a loop, either an explicit one like this:

foreach my $rec (@records)
{
    $hash{$rec} = $counter++;
}

or an implicit one like one of these:

%hash = map {$_ => $counter++} @records;
# or:
$hash{$_} = $counter++  for @records;
2
votes

This code should generate the proper output, where my-text-file is the path to your data file:

my %hash;
my $counter = 0;
open(FILE, "my-text-file");
while (<FILE>) {
 chomp;
 $counter++;
 $hash{$_} = $counter;
}
# Now to sort
foreach $key (sort(keys(%hash))) {
 print $key . ":" . $hash{$key} . "\n";
}

I assume you want to sort the hash aplhabetically. keys(%hash) and values(%hash) return the keys and values of %hash as an array, respectively. Run the program on this file:

f
a
b
d
e
c

And we get:

a:2
b:3
c:6
d:4
e:5
f:1

I hope this helps you.