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

I'm working on a project in which I have to send customer data(card number, address, zip code, etc.) to a credit card processor. This particular processor requires third street to be sent as 3rd street for AVS(Address Verification System) to work correctly. Has anyone seen a module that will do this conversion?

I really don't want to build a huge hash with all of these values, which no matter how big I make it, will still be incomplete.

Replies are listed 'Best First'.
Re: Address conversion
by fglock (Vicar) on May 27, 2003 at 16:46 UTC
      fglock++ beat me to the punch. However, please note that there are a few slight bugs with Lingua-EN-Numericalize. For instance, if you just feed in "Third Math St." it will return "3 Ma St.". Also, if any word ends in zero, four, fif, six, seven, eigh, or nin, it will put the corresponding number there. So "Thornin" becomes "thor9". This only happens at the end of the string. In the past, I've had to split /[\s-]/ the address and check each string to make certain it is numeric by checking str2nbr =~ /^\d+$/ then reevaluate the numerics together to come out with what it ought to be.

      Just wondering, what cc processor do you use?

      antirice    
      The first rule of Perl club is - use Perl
      The
      ith rule of Perl club is - follow rule i - 1 for i > 1

        Thanks for your help.

        I think this gives me what I need, along with Lingua::EN::AddressParse I can hopefully prevent most errors.

        We are currently certifying to Vital.
Re: Address conversion
by BrowserUk (Patriarch) on May 27, 2003 at 18:16 UTC

    This could be extended to deal with greater that Ninety-Nine Hundred Ninety-Ninth Street if needed:) Probably has bugs and limitations, but then what doesn't.

    #! perl -slw use strict; my $re_road = qr[(?: street | avenue | road | way )]xi; my $re_11 = qr[(?: first | second | third | fourth | fifth | sixth | seventh | eight | nineth )]xi; my $re_12 = qr[(?: tenth | eleventh | twelveth | thirteenth | fourt +eenth | fiveteenth | sixteenth | seventeenth | eighteenth | nineteenth + )]xi; my $re_21 = qr[(?: one | two | three | four | five | six | seven | eight | nine | ten )]xi; my $re_22 = qr[(?: tenth | eleven | twelve | thirteen | fourteen | +fiveteen | sixteen | seventeen | eighteen | nineteen )]xi; my $re_23 = qr[(?: twenty | thirty | fourty | fifty | sixty | seventy | eighty | ninety )]xi; my $re_3 = qr[(?: hundred | thousand )]xi; my $re_all = qr[ (?: (?: ($re_23) [\s-]+ )? ($re_21) [\s-]+ ($re_3) \s+ )? (?: (?: (?: (?: ($re_23) [\s-]+ )? ($re_11) ) | ($re_12) ) ) \s+ $re_road ]xi; my %teens = ( one=>1, two=>2, three=>3, four=>4, five=>5, six=>6, seven=>7, eight=>8, nine=>9, ten=>10, eleven=>11, twelve=>12, thirteen=>13, fourteen=>14, fiveteen=>15, sixteen=>16, seventeen=>17, eighteen=>18, nineteen=>19, ); my %teenths = ( first=>1, second=>2, third=>3, fourth=>4, fifth=>5, sixth=>6, seventh=>7, eigth=>8, nineth=>9, tenth=>10, eleventh=>11, twelfth=>12, thirteenth=>13, fourteenth=>14, fifteen +th=>15, sixteenth=>16, seventeenth=>17, eighteenth=>18, nineteenth=>19, ); my %orties = ( twenty=>20, thirty=>30, fourty=>40, fifty=>50, sixty=>60, seventy=>70, eighty=>80, ninety=>90, ); my %mags = ( hundred=>1e2, thousand=>1e3, million=>1e6, ); my @bits; while( <DATA> ) { @bits = grep{$_} @bits if @bits = $_ =~ m[$re_all]; my $n=0; for( @bits ) { $n += $orties{$_} if exists $orties{$_}; $n += $teens{$_} if exists $teens{$_}; $n *= $mags{$_} if exists $mags{$_}; $n += $teenths{$_} if exists $teenths{$_}; } $n .= ( 'th', qw[st nd rd], ('th')x6 )[substr($n,-1)]; print join '|', @bits, " => $n"; } __DATA__ third street fourth avenue nineteenth street twenty-fifth way fifty-first street one hundred twenty third street three hundred thirty third street thirty-three hundred seventy-fifth street

    Output

    D:\Perl\test>261018 third| => 3rd fourth| => 4th nineteenth| => 19th twenty|fifth| => 25th fifty|first| => 51st one|hundred|twenty|third| => 123rd three|hundred|thirty|third| => 333rd thirty|three|hundred|seventy|fifth| => 3375th

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
Re: Address conversion
by Zed_Lopez (Chaplain) on May 27, 2003 at 17:36 UTC
    { my @thsuffix = (qw(th st nd rd), (th) x 6); sub th { my $n = shift; return $n. (($n > 9 and $n < 14) ? 'th' : $thsuffix[substr($n,-1)]) +; } }
    and, of course, there are a million other ways to do it.
    sub th { my $n = shift; for ($n) { return $n . "st" if /1$/ and !/11$/; return $n . "nd" if /2$/ and !/12$/; return $n . "rd" if /3$/ and !/13$/; return $n . "th"; } }
Re: Address conversion
by danb (Friar) on May 28, 2003 at 01:38 UTC
    I don't know if this would be of any assistance or not, but you might check it out: USPS has a free XML API for doing address verification, standardization, zip/state lookup, and etc. You can read about it at their website. I'm nearly complete with a complimentary tool that utilizes their API (and the one provided by UPS) to calculate shipping cost. I plan to release it on CPAN in the coming weeks.
      This doesn't seem to be a very good option mainly due to the Terms and Conditions of Use that most people might skip over.

      * User agrees to use the USPS Web site, APIs and USPS data to facilitate USPS shipping transactions only.
      * User may not use USPS Web Tools APIs in connection with any other payment system other than the USPS Pay@Delivery Service.
      * Developer may package software which interfaces with any or all USPS APIs with password and ID for resale or distribution to others only after registering with USPS as a Developer and agreeing to these Terms and Conditions of Use.


      So you can only use the API to get info if you're using USPS shipping and you must use their services to handle monetary transactions. This solution doesn't seem to help with the problem at hand, unless he wants to dump his cc processing service. Furthermore, this particular problem doesn't require anyone to verify that the address exists but rather compensate for the expected data format of his processing service's AVS. As for your modules that you're releasing to CPAN, be certain to include the terms of use as it is yet another requirement for use of the API.

      antirice    
      The first rule of Perl club is - use Perl
      The
      ith rule of Perl club is - follow rule i - 1 for i > 1