Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I have a file <FILE1> that contains data like this:

NY,00501,00501
NY,00544,00544
...and so on

It's state abbreviation, zip code range for that state (start, end)

I have another file <FILE2> for each state that contains all the zip codes and cities for that state in this format:

10918|Chester
10919|Circleville
...and so on

What I want to do is read in another file <FILE3> that contains a zip code I want to match with a city. So, the logic is...

Read in zip code from <FILE3>
check against data in <FILE1>
if zip code falls in the range then open the proper state file <FILE2>
match the zip from <FILE3> to the city in <FILE2>
return the zip, city, state

I got this to work with using nested foreach loops but seems slow, especially with a huge list of zips to check. I'm thinking that is not a very optimal way to do this. It was suggested I use a hash of hashes but this newbie got confused ;-)

Any ideas?? Thanks Tim

Replies are listed 'Best First'.
Re: How to match zip code to city,state
by PodMaster (Abbot) on Oct 26, 2002 at 01:31 UTC
    I suggest you use DB_File and have at least one hash looking like
    my %ZipTo = ( 95119 => 'San Jose, CA' );
    This will simplify things considerably. If you need a reverse mapping, well, just reverse the hash. You can use DB_File to match partial keys, and you can have duplicate keys.

    Anyway, that's what I'd do.

    ____________________________________________________
    ** The Third rule of perl club is a statement of fact: pod is sexy.

Re: How to match zip code to city,state
by Enlil (Parson) on Oct 26, 2002 at 04:23 UTC
    First you might also try perusing perldsc for good info on Hashes of Hashes, Arrays of Arrays, Arrays of Hashes,etc.

    If the files are not all that big (to justify using a database, as I would do if the files were big, and then run an SQL Query), or I wanted a little practice honing up my hashes of hashes skills I might do the following (I have removed some code to let you work out some details, this is probably not the optimal way but it is one way):

    My logic goes as follows:

    1. open <FILE2> and place all the cities in a hash keyed by zipcode something like:

    chomp($line) #line from FILE2 my ($zip_code,$city) = split /\|/,$line; $zip_city{$zip_code} = $city; #insert city into hash

    2. open <FILE1> again split it and compare the keys in my original hash setting the state and city in a hash again keyed against zip (the delete $zip_city{$current_zipcode}; part is so that I don't continue to go over zips I already have a state for, you could also put a last; so it would not continue reading from <FILE1> once the hash %zip_city contained no keys).

    chomp($line); my ($state,$min,$max) = split /,/,$line; foreach my $current_zipcode ( keys %zip_city ) { if ( $current_zipcode >= $min and $current_zipcode <= $max ) { $zip_city_state{$current_zipcode}{city} = $zip_city{$current_zipc +ode}; $zip_city_state{$current_zipcode}{state} = $state; delete $zip_city{$current_zipcode}; } }
    3. Lastly for each line in <FILE3> I would see if the zipcode (assuming you put it in a variable called $zipfrom3)existed in the second hash (%zip_city_state hash) and if it does print the info you want:
    print "$zipfrom3,$zipzip_city_state{$zipfrom3}{city}, $zip_city_state{ +$zipfrom3}{state}\n";
    or else complain that it did not exist in the hash (if you use warnings; it will do a good job of complaining if you don't check for the existance of a zip in the hash first, but you should check for the existance anyhow).

    -enlil

Re: How to match zip code to city,state
by Anonymous Monk on Oct 26, 2002 at 01:42 UTC
    You might try CPAN. Geo::PostalCode lets you look up lat, lon, city and state by zip. There may be other packages.