Solved

Question on perl function

Posted on 2003-10-31
8
180 Views
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


0
Comment
Question by:DancingFighterG
8 Comments
 
LVL 2

Expert Comment

by:ultimatemike
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.
0
 
LVL 28

Expert Comment

by:FishMonger
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";
}
0
 
LVL 28

Expert Comment

by:FishMonger
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;
0
 
LVL 18

Expert Comment

by:kandura
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.

examples:
# 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.
Example:
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;

HTH,

Kandura
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Author Comment

by:DancingFighterG
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?
0
 
LVL 20

Expert Comment

by:jmcg
ID: 9673044
You could do

use Data::Dumper;

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

0
 
LVL 28

Accepted Solution

by:
FishMonger earned 150 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;
0
 

Author Comment

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

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Email validation in proper way is  very important validation required in any web pages. This code is self explainable except that Regular Expression which I used for pattern matching. I originally published as a thread on my website : http://www…
There are many situations when we need to display the data in sorted order. For example: Student details by name or by rank or by total marks etc. If you are working on data driven based projects then you will use sorting techniques very frequently.…
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…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

744 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

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now