More Virtual Promote ... Search Engine Forums · Webmasters Toolkit · Free Website Templates · Scumware.com
.
Virtual Promote Gazette Home Subscribe/Unsubscribe Archives  
.

gazette



Issue # 209 (02-13-2004)

Changing the Internet, One Thing at a Time

Coders Corner
Hashes to Hashes, Dust to Dust: Migrating from Perl to PHP

I've been a PERL hack for years and years, and I'm slowly making the transition to PHP... for varioius reasons. PHP, as you might know, was developed by a former PERL hack who liked PERL, but wanted a more Web-friendly language. The similarities in the two languages are evident, with much of the same functinality achieved in slightly different ways. In some cases, PHP nearly mirrors PERL, but in other cases, as with the way it deals with "Associative Arrays" (hashes to you PERL geeks), there are some things that take a little bit of adjustment. Let's look, this week, at defining and sorting hashes in both languages.

We're going to create a simple in-memory database using hashes, sort it by any field we want, and print it out.

First, using PERL...

First, define an empty array. What we're going to do is have an array, where each element in the array is a hash, which contains named fields for our database as well as their corresponding values.
my @database = ();
Now, "push" the records into the array. Effectively, think of an array as the inbox on your desk, and each record as a piece of paper with information on it. In this example, on that paper, we have people's names and phone numbers, and we're pushing each of them on top of the last piece of paper in the box.
push @database, { firstname=>"John", lastname=>"Cokos", phone=>"800-555-1212" };
push @database, { firstname=>"Fred", lastname=>"Smith", phone=>"866-555-1212" };
push @database, { firstname=>"Suzie", lastname=>"Queue", phone=>"888-555-1212" };
push @database, { firstname=>"James", lastname=>"Peach", phone=>"877-555-1212" };
At this point, we have an "array of hashes," or in English, four sheets of paper, each with information about a person, on top of each other in a pile on your desk. What we want to do now is sort them by last name and print them out. In PERL, the way that this works is that you iterate through the array (go through your papers one by one) over an over again comparing the last names to get the papers in alphabetical order. Using the PERL "sort" subfunction within the "foreach" accomplishes this quite nicely in one line:
foreach my $record ( sort { $a->{lastname} cmp $b->{lastname} } @database) {
    print "Name: $record->{firstname} $record->{lastname} -- $record->{phone}\n";
}
This loop assigns a variable ($record) to each element in the array. PERL knows that each record has some field names (firstname, lastname, phone) and data that matches. The "cmp" within the sort tells PERL to sort the information alphabetically. The order of things in the sort block ($a ... $b) tells it to sort top-down (A-Z). If we reversed that and said ($b ... $a), it would sort them in reverse (Z-A). Along with the sort order, we told the sort function to sort on the "lastname" field of each record. That line effectively says "Sort the elements in the array alphabetically from Ato Z, on the lastname field in the database."

Now, in PHP, the thought process is essentially the same, but getting there is slightly different:

As with PERL, we start by defining an empty array to hold everything.
$database = array();
Also like PERL, we're going to "push" our data into that array. Notice that with PERL, you were able to just list the fields/data in a simple list. With PHP, you need to tell the push command that you're pushing an array, and then list the array elements (the fieldname/data assignments) as a separate unnamed array:
array_push ( $database, array( "firstname"=>"John", "lastname"=>"Cokos", "phone"=>"800-555-1212" ) );
array_push ( $database, array( "firstname"=>"Fred", "lastname"=>"Smith", "phone"=>"866-555-1212" ) );
array_push ( $database, array( "firstname"=>"Suzie", "lastname"=>"Queue", "phone"=>"888-555-1212" ) );
array_push ( $database, array( "firstname"=>"James", "lastname"=>"Peach", "phone"=>"877-555-1212" ) );
In PHP, there's no differentiation between a "hash" (record) and an array. They're basically the same thing. If you supply a fieldname, PHP turns it into an associative array (hash) for you. This is nice and simple, in that unlike PERL, you don't have to worry about using "% or @" symbols to define the variable type, and you don't have to switch between [] and {} to get to the elements. However, PHP doesn't provide a natively inline sort utility as does PERL, so getting the data within this array sorted isn't quite a one-liner as it was in PERL.

Instead, we have to run our $database through a home grown sorting function, called "aasort". This function, when passed an array name, and a field name, will sort the array, on that field, in the order specified ("+" for A-Z and "-" for Z-A). aasort() also allows for you to specify multiple fields to sort, for example .... "+lastname,-firstname" would sort lastnames A-Z and within them, firstnames from Z-A.

Here's how you call "aasort()" for use in our example:

aasort($database, "-lastname");
Once it returns the sorted data, running through it and printing it basically mirrors the PERL version...
foreach ( $database as $record ) { 
   print "Name: " . $record['firstname'] .  " " . $record['lastname'] . "--" .  $record['phone'] . "\n";
}
Here's the "aasort()" function for your reference and use. It's logic is explained using comments throughout.
function aasort(&$array, $howto) {

  // Get out if we didn't get an array sent to us
  if ( ! is_array($array) ) { return; }
      
  $sort_rule = '';

  // Create an array of sorting rules, based on the "howto" portion of
  // how we were called.  These options would be separated by ","
  $args = explode(",", $howto);
    
  // For each rule that we were sent, sort the array based on that field name
  foreach($args as $arg) {

      // What field name are we sorting on ?
      $order_field = substr($arg, 1, strlen($arg));
 
      // Go through each record of the array, creating a new array as we go
      foreach($array as $array_row) {
          $sort_array["$order_field"][] = $array_row[$order_field];
      }

      // Sort this built-on-the-fly array either A-Z or Z-A, based on how we were called
      $sort_rule .= '$sort_array["'.$order_field.'"], '.($arg[0] == "+" ? SORT_ASC : SORT_DESC).',';
  }
  
  // Now we have a really complicated rule to send to PHP's array_multisort() function to get
  // it all in the right order.
  eval ("array_multisort($sort_rule".' &$array);');
  reset(&$array);
  
  // Note that we sent in the original array by reference, so there's no
  // need to return anything.
}


Read the Coders Corner section from the Last Issue or in the Following Issue


JimWorld Member comments and feedback ...

Add your own comment ....

We accept comments to Gazette Articles only by registered JimWorld.com members. If you are not yet a member, please join now. Membership is free, and entitles you to not only post comments here, but also to participate in our discussion forums, as well as other areas of the JimWorld.com network.

If you are currently a JimWorld member, your userid and password will allow you to login with the form below.

Login
Forget your password?
Password

 

 

Sponsored Links

Search for a Free Domain
The Virtual Promote Toolkit is hosted by the experts at SimpleNet. You should be, too! Whether building a new site or transferring one, there is no other hosting platform comparable to SimpleNet’s; hosting for less than $5/month.
Search for the following tlds: .com, .net, .org, .info, .biz, & .us
Already have a domain or site? Move it to SimpleNet


Hyperseek Search Engine
Member Spotlight
Free Photographs
Free photographs for non-commercial use. (Enterprise)
spacer

 

 

   

© 1995 - 2004  ·  iWeb, Inc DBA JimWorld Productions