Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium


Question on perl function

Posted on 2003-10-31
Medium Priority
Last Modified: 2010-03-04
Hello, I'm tyring to use perl to reference to a hash and then return the contents of ther hash in an array. Within this function that I am building I am entering in the data in the hash in the form last name, firstname, age. When the value is returned I want the value to come out of the array age,firstname, lastname. I also tyring to get it to sort. Since I know more about sorting arrays I was thinking of just sorting the array instead of the hash. Right now, the info is not reading the hash correctly. This is what I have code wise:

%people = ("Richardson, Greg" -> 22, "Zog, Mike" -> 23, "Boston, Doug -> 24, "Rudolph, Josh" -> 25, "Fritz, Stacy" -> 26)

foreach @child (keys %people) {
print "$child, $people{$child}

@people = keys %people, values %people
@sorted_people = sort{lc($b) cmp (lc($a)} @people
print @sorted_people

Any help would be great

Question by:DancingFighterG

Expert Comment

ID: 9660011
You can actually sort the hash without creating an array.  Try this:

%people = ("Richardson, Greg" -> 22, "Zog, Mike" -> 23, "Boston, Doug -> 24, "Rudolph, Josh" -> 25, "Fritz, Stacy" -> 26)

foreach ( sort { lc($b) cmp lc($a)}  keys (%people) ) {

      my @names = split /, /;
      my $age = $people{$_};


so $names[0] will have the last name, and $names[1] will contain the first name.
LVL 28

Expert Comment

ID: 9661184
ultimatemike showed you an excelent method for for doing the sort (in reverse order).  However, instead of splitting the name into an array, I'd use 2 scalars and I'd make sure the names were translated to titlecase.  My example uses to print statements to show the difference in style of output.

%people = ("richardson, greg" => 22, "Zog, Mike" => 23, "Boston, doug" => 24, "Rudolph, Josh" => 25, "Fritz, Stacy" => 26);

foreach $person ( sort { lc($a) cmp lc($b)}  keys (%people) ) {

   $person =~ s/(\w+)/\u$1/g;  # translate to titlecase
   ($last, $first) = split /, /, $person;

   print "$person is $people{$person} years old\n";
   print "$first $last is $people{$person} years old\n\n";
LVL 28

Expert Comment

ID: 9661235
If you really need to use an array, then instead of those print statements, you'd push the info onto the array.

Like this:

push @last_first, "$person $people{$person}";
push @first_last, "$first $last $people{$person}";

Then you can print the array somewhere else in your script. like this:

print "$_\n" foreach @last_first;
print "$_\n" foreach @first_last;
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

LVL 18

Expert Comment

ID: 9662464
Why not change your data to another structure? I like using record-style hashes for this, because it adds flexibility in both sorting and displaying.
I would use something like:
$person = {
    firstname => 'Greg',
    lastname => 'Richardson',
    age         => 22

First I'll convert your %people hash into an array of person records:
my @people = ();
while(my ($k, $v) = each %people) {           # loop over elements
    my ($lname, $fname) = split /, /, $k, 2;    # split the key into name parts
    push @people, {                                      # add anonymous hash to the array
        firstname => $fname,
        lastname  => $lname,
         age         => $v

now you can sort your array on one or more keys of the records.

# sort by last name
my @ns_people = sort {
     $a->{lastname} cmp $b->{lastname}
    } @people;

# sort by last name, firstname ascending, age descending
my @lfa_people = sort {
     $a->{lastname} cmp $b->{lastname} ||        # first sort on last name
     $a->{firstname} cmp $b->{firstname} ||        # next on first name
     $b->{age}          <=> $a->{age}                   # finally, on age descending
    } @people;

you can put whatever criteria into the sort { } block that you need. (Including doing a case insensitive sort).

Outputting your data becomes much more flexible too, since you have separate fields for every part of the person.
foreach(@lfa_people) {
    printf "Age: %d, name: %s %s\n", $_->{age}, $_->{firstname}, $_->{lastname};

Also it makes it easy to filter your data. Say you would only want the people with age 25:
@tf_people = grep { $_->{age} == 25 } @lfa_people;



Author Comment

ID: 9672884
Quick question FishMonger, is there any way I can print out the hash itself so I can show the original has data and then the array version?
LVL 20

Expert Comment

ID: 9673044
You could do

use Data::Dumper;

print Dumper( \%people, \@lfa_people);

LVL 28

Accepted Solution

FishMonger earned 600 total points
ID: 9673579
After looking over the script that I posted, I noticed an error I made reguarding the the titlecase.  Here's the corrected script that also prints out the hash before and after the sorting (as well as the sorted array) and uses the CSV formating (I think you were wanting) .

%people = (
           "richardson, greg" => 22,
           "zog, mike" => 23,
           "Boston, doug" => 24,
           "Rudolph, Josh" => 25,
           "Fritz, Stacy" => 26

print "Prior to sorting the hash\n";
print "\t$_ $people{$_}\n" foreach (keys %people);

print "\nAfter sorting the hash\n";
foreach $person ( sort { lc($a) cmp lc($b)}  keys (%people) ) {
   ($last, $first) = split /, /, $person;
   $last =~ s/(\w+)/\u$1/;  # translate to titlecase
   $first =~ s/(\w+)/\u$1/;  # translate to titlecase
   print "\t$people{$person},$first,$last\n";
   push @first_last, "$people{$person},$first,$last";

print "\nSorted hash put into an array\n";
print "\t$_\n" foreach @first_last;

Author Comment

ID: 9674633
Thanks FishMonger. I could not figure out how to print out the hash right. Thanks again. :)

Featured Post


Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Many time we need to work with multiple files all together. If its windows system then we can use some GUI based editor to accomplish our task. But what if you are on putty or have only CLI(Command Line Interface) as an option to  edit your files. I…
I have been pestered over the years to produce and distribute regular data extracts, and often the request have explicitly requested the data be emailed as an Excel attachement; specifically Excel, as it appears: CSV files confuse (no Red or Green h…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Six Sigma Control Plans
Suggested Courses

578 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question