Nano HE
Nano HE

Reputation: 9307

Question on Hash Sort and Print in Perl

I've got trouble on how to print my hash contents.

Code snippet as this,

#!/usr/bin/perl -w
use strict;
use warnings;

my (%data, $keyword);

while (my $line = <DATA>){
    next unless $line =~ /\S/;
    chomp $line;
    if ($line =~ /^Keyword/){
        $keyword = $line;
    }
    else {
        push @{$data{$keyword}}, $line;
    }
}

# How to sort by keys using while loop?
while ( my ($k,$v) = each %data ) { 
    print "$k => $v\n";
}

# BTW, foreach loop sorting works.
#foreach my $key (sort (keys(%data))) {
#   print "$key \t$data{$key}\n";
#}

__DATA__
Keyword1
data1 a
Keyword2
data2 a
data2 b
data2 c
Keyword3


data3 a
data3 b


Keyword4
data4 a
data4 b

Output:

D:\learning\perl>sc4.pl
Keyword3 => ARRAY(0x18418fc)
Keyword1 => ARRAY(0x28925c)
Keyword2 => ARRAY(0x2892fc)
Keyword4 => ARRAY(0x184360c)

Actually, I don't think the Keyword1 value (data1 a, Only one line)is ARRAY. But the output still showed it was an array.

Could you give me some suggestions on how to print it correctly.

Appreciated for your input.

[update]

I update my code for while loop to try to print the values array. but still failed.

while ( my ($k,@v) = each %data ) {
    print "$k\n";
    foreach (@v) {
    print Dumper (@v);
    print "$_\n";
    }
}

Output:

D:\learning\perl>sc4.pl
Keyword3
$VAR1 = [
          'data3 a',
          'data3 b'
        ];
ARRAY(0x189a674)
Keyword1
$VAR1 = [
          'data1 a'
        ];
ARRAY(0x28925c)
Keyword2
$VAR1 = [
          'data2 a',
          'data2 b',
          'data2 c'
        ];
ARRAY(0x2892fc)
Keyword4
$VAR1 = [
          'data4 a',
          'data4 b'
        ];
ARRAY(0x1841a74)

I already defined another foreach loop included by while loop to handle the array values. But it doesn't work well. I don't know why?

Upvotes: 2

Views: 3505

Answers (3)

Axeman
Axeman

Reputation: 29854

Simplest way I know:

use Smart::Comments;
...
### %data

see Smart::Comments.

It's not what you want to do as a final step, I'm sure. But it works in those cases where you just want to peek at what you've collected.

Another way is similar:

use Data::Dumper; 
say Data::Dumper->Dump( [ \%data ], [ '*data' ] );

Upvotes: 1

Nano HE
Nano HE

Reputation: 9307

Eventually, I found the solution to print Array of array in Perl.

I updated my While Loop as below.

while ( my ($k,@v) = each %data ) {
    print "$k\n";
    print Dumper (@v);
    for (my $i = 0; $i < @v; $i++) {
        for (my $j = 0; $j < @{$v[$i]}; $j++) {
             print STDOUT "\$i: " . $i . " \$j: " . $j . " value: " . $v[$i][$j] . "\n";
        }
    }
}

Output:

D:\learning\perl>sc4.pl
Keyword3
$VAR1 = [
          'data3 a',
          'data3 b'
        ];
$i: 0 $j: 0 value: data3 a
$i: 0 $j: 1 value: data3 b
Keyword1
$VAR1 = [
          'data1 a'
        ];
$i: 0 $j: 0 value: data1 a
Keyword2
$VAR1 = [
          'data2 a',
          'data2 b',
          'data2 c'
        ];
$i: 0 $j: 0 value: data2 a
$i: 0 $j: 1 value: data2 b
$i: 0 $j: 2 value: data2 c
Keyword4
$VAR1 = [
          'data4 a',
          'data4 b'
        ];
$i: 0 $j: 0 value: data4 a
$i: 0 $j: 1 value: data4 b

Upvotes: 0

Nathan Fellman
Nathan Fellman

Reputation: 127428

First of all, you need to define what you mean by "sort". Are you sorting by keys? By values?

If you're sorting by key, the simplest is to use Perl's built-in sort like this:

foreach (sort keys %data) {
    print "$_ => $data{$_};
}

If you want to sort by value you can define an anonymous sort function that sorts by value:

foreach (sort {$data{$a} <=> $data{$b}} keys %data) {
    print "$_ => $data{$_};
}

And if you want any other sorting, you can define a function that operates on the global variables $a and $b (they are set automatically by sort) and returns -1, 0 or 1 depending the sort order.

If you must do it with a while loop, I'll need to give it some more thought.

Upvotes: 7

Related Questions