Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic

More elegant way of doing "ordered hash"?

by PopeFelix (Beadle)
on Oct 09, 2013 at 22:01 UTC ( #1057626=perlquestion: print w/replies, xml ) Need Help??
PopeFelix has asked for the wisdom of the Perl Monks concerning the following question:

I have the following data structure that I'm effectively treating as an ordered hash. I realize that I could use Tie::IxHash, but for various reasons (see below) I don't want to do that.

my $spec = { 'Parameters' => [ 'shipmentIncrementId' => { 'required' => 1, 'type' => 'string', }, 'carrier' => { 'required' => 1, 'type' => 'ups|usps|dhl|fedex|dhlint|custom', }, 'title' => { 'required' => 1, 'type' => 'string', }, 'trackNumber' => { 'required' => 1, 'type' => 'string', }, ], 'Response' => 'scalar', };

I'm iterating over the keys like so:

my @params = $thing->{'Parameters'}; for my $index (0..$#params) { next if $index % 2 != 0; my $parameter = $params[$index]; my $spec = $params[$index + 1]; # do something from here... }

Is there a more elegant way of doing that?

As to why I'm not doing Tie::IxHash: I'm using this to specify dynamic methods like so:

define_method 'foo' => { 'Parameters' => [ 'bar' => { 'required => 1, 'type' => 'string', }, 'baz' => { 'required => 1, 'type' => 'string', }, ] };

Note that the application requires the arguments to be in order. I'm not sure how I'd use Tie::IxHash in that situation.

Replies are listed 'Best First'.
Re: More elegant way of doing "ordered hash"?
by kcott (Chancellor) on Oct 10, 2013 at 08:00 UTC

    G'day PopeFelix,

    for my $index (0..$#params) { next if $index % 2 == 0; my $parameter = $params[$index]; my $spec = $params[$index + 1]; # do something from here... }

    Is there a more elegant way of doing that?

    How about:

    for (grep { not $_ % 2 } 0 .. $#params) { my ($parameter, $spec) = @params[$_, $_+1]; ... }

    [ You've got a couple of typos: the 1st $spec becomes $thing; you assign an arrayref to @params ]

    -- Ken

Re: More elegant way of doing "ordered hash"?
by boftx (Deacon) on Oct 09, 2013 at 22:19 UTC

    Right off the top it looks like the 'define_method' code is accepting the value for 'Parameters' as a hash ref instead of an array ref so I'm not sure you are going to be keeping the order of the keys to begin with, especially with the latest version of Perl.

    That aside, unless you are in a position to rewrite the app (which I would guess is significant in size) to use named parameters instead of positional you have probably come up with the best way to do what you want. The entire problem disappears if you can switch to named params. Plus, you can take advantage of CPAN modules to enforce type checking, etc, like you are currently doing.

    Of course, if you can make the change, then go whole-hog and covert to Moose since what you have here looks a lot like someone tried to invent Moose with positional params.

    On time, cheap, compliant with final specs. Pick two.

      Value for Parameters is an arrayref.

      As for sending named parameters, I can't do that because what I'm doing is wrapping XML-RPC calls to Magento, and I haven't found a way to get XML::RPC to send named params.

      And yes, this was partially inspired by Moose. :)

        whoops! There was a typo there. Parameters should definitely be an arrayref in define_api_method

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1057626]
Approved by Old_Gray_Bear
[marto]: in the sense that for various values of "a while ago" it would not have been possible (and arguable still isn't) to have a fingerprint of every piece of commercially released music to compare against.
[marto]: a co-worker refers to the late 1980s as "a while ago"
[Veltro]: Like I said before, I ment the solution as a whole
[Veltro]: People thought it was not possible.
[marto]: and until recently it wasn't and arguable (for some samples) probably isn't
[Veltro]: How did we get here? Oh yeah, advertisement. So let's get back there. What I ment to say is that I think it is possible to create an algorithm that filters out advertisement
[Veltro]: And yes, maybe your decoder needs the cloud to do so.

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (8)
As of 2018-05-24 12:12 GMT
Find Nodes?
    Voting Booth?