httpraku

What is an idiomatic way to convert a query to a hash


The response to an HTTP request is a string like 'one=iwejdoewde&two=ijijjiiij&three=&four=endinghere'

I want to put this query into a hash. My solution is

my $s = 'one=iwejdoewde&two=ijijjiiij&three=&four=endinghere';
my %h = $s.comb(/<-[&]>+/).map({ my @a = .split(/\=/); @a[0] => @a[1] }) ;
say %h;
#                                                                                   
# {four => endinghere, one => iwejdoewde, three => , two => ijijjiiij}
#

I think the $s to %h looks ugly. However, it handles the three= segment without breaking.

It seems there should be a better way, particularly making a Pair from the results of the split.

This seems to work for an individual pair:

my $s='one=two';
say $s.match( / (.+) \= (.*) / ).pairup

but putting it inside the .map leads to an unexpected result

my $s = 'one=iwejdoewde&two=ijijjiiij&three=&four=endinghere';
my %h = $s.comb(/<-[&]>+/).map( *.match(/ (.+) \= (.*) /).pairup )
say %h;
#
# {one    iwejdoewde => (「two」 => 「ijijjiiij」), three      => (「four」 => 「endinghere」)}
#

Solution

  • Assuming the arguments of the query are separated by &, and each argument has a = separator in them, then I'd suggest this would be the easiest way to solve this:

    my $s = 'one=iwejdoewde&two=ijijjiiij&three=&four=endinghere';
    my %h = $s.split('&').map(|*.split("=",2));
    say %h;  # {four => endinghere, one => iwejdoewde, three => , two => ijijjiiij}
    

    Note that the trick is really the | on the result of the second split that will feed (slip) the values separately into the initialization of the %h hash (instead of List entries).

    If you find the | a bit obscure, you can be more explicit with *.split("=",2).Slip.