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

I feel like there must be a more elegant way to do this. I'm getting data from an online service, and sometimes I get a result with 1 hash, and other times a list of hashes. So what I'm doing now is:
if ($content->{Addresses}{ArrayOfAddressResponse}{AddressResponse} =~ +/HASH/) { foreach my $response ( keys %{$content->{Addresses}{ArrayOfAddressResp +onse}} ) { ...do stuff...
and then
if ( $content->{Addresses}{ArrayOfAddressResponse}{AddressResponse} =~ + /ARRAY/) { foreach my $response ( @ {$content->{Addresses}{ArrayOfAddressResponse +}{AddressResponse}} ) {
The thing is, the "stuff" I'm doing ends up looking identical like:
print "street: $response->{Street}<br>"; print "street2: $response>{Street2}<br>"; print "apt: $response->{UnitNumber}<br>";
So it just seems very wasteful. I've thought about just making all the print statements a subroutine. But it's the two "if" statements that seem kinda clunky to me. Any input would be greatly appreciated (again)!

Replies are listed 'Best First'.
Re: Changing a loop based on the nature of a reference
by Your Mother (Archbishop) on Nov 05, 2009 at 05:41 UTC

    Stab in the dark: XML::Simple? You might look at the ForceArray => 1 option. IIRC that would solve your issue by making them all arrays.

    Tangent-

    if ( $content->{Addresses}{ArrayOfAddressResponse}{AddressResponse} =~ /ARRAY/ )

    -is probably better as something like-

    my $item = $content->{Addresses}{ArrayOfAddressResponse}{AddressRespon +se}; if ( ref($item) eq 'ARRAY' ) ...

    Update: there's also this sort of thing-

    my $address_ref = $content->{Addresses}{ArrayOfAddressResponse}{Addres +sResponse}; my $addresses = ref($address_ref) eq 'HASH' ? [ $address_ref ] : $address_ref;

    -which will always give you back an array ref of hashes. Note that it doesn't account for unexpected values, e.g., undef, a scalar, a different type of ref, etc.

Re: Changing a loop based on the nature of a reference
by colwellj (Monk) on Nov 05, 2009 at 05:49 UTC
    Why not pretend that your returned hash is actually a list of 1 hash.
    i.e
    my @myarray; push @myarray, @{$content->{Addresses}{ArrayOfAddressResponse}{Address +Response}}; foreach my $response ( @myarray ) { do stuff... }

    I think this might work. You may even be able to directly reference without the push.
    John
      Your Mother: On the money, yes, XML::Simple. And I think that is likely the best way to fix it *this* time--thanks! I also like your terniary method. Mostly because I look for any opportunity to use the terniary operator :-) Nah but actually that seems pretty nice. :-) Thanks to all!