Как я могу взорвать строку в хеш? - PullRequest
0 голосов
/ 17 октября 2011

У меня есть строка

"myhashkey?key1=val1&key2=val2&key3=val3&key4=val4"

, которую я хочу взорвать в

myhashkey => {
   key1 => val1,
   key2 => val2,
   key3 => val3
}

Я также хочу свернуть это обратно в ту же строку.

Такдалеко, что я придумал, это довольно грязно, используя индекс и пытаясь построить значения вручную

        $arg = $_[0];

#if arg has = it may be key=val string
        if(index($arg,'=') > -1 ){

#if arg has & character it might be key=val&key1=val

            if(index($arg,'&') > -1 ){

                #$arg =~ m/[=&\?]/
                @r = split(/[=&\?]/,$arg);
                my $hashkey = shift(@r)
                my %values = @r;
                return $class->$orig( key => $k, $value => \%values );
                ... 

            }else{
                @r = split('=',$arg);
                return ( key => $r[0], $value => $r[1] );
            }

        }

Я не знаю, насколько дорого обходятся index (), split () и join () функции против других методов достижения этого.Я думал, может быть, я мог бы использовать map + grep, но я не был уверен, как создать rergex для grep.

Я также не хочу изобретать велосипед, так что надеюсь, у кого-то есть лучшее представление о том, как это сделать.,

updated Кстати, это происходит в подпрограмме Moose BUILDARGS, поэтому я не хочу использовать такой модуль, как URI, для анализа строки каждый раз.

Вот как я использую функцию в BUILDARGS

my $w = My::Param->new( 'hashkey?key1=val1&key2=val2&key3=val3');
my $x = My::Param->new( key => 'x', value => '7' );
my $y = My::Param->new( 'y=123' );

Производит это на принтере Dumper (*)

{ 'key1' => 'val1', 'key2' => 'val2', 'key3' => 'val3' }
bless( { 'key' => 'hashkey', 'meta_info' => [ #0 'hashkey?key1=val1&key2=val2&key3=val3' ], 'value' => { 'key1' => 'val1', 'key2' => 'val2', 'key3' => 'val3' } }, 'My::Param' )
bless( { 'key' => 'x', 'meta_info' => [ #0 'key', #1 'x', #2 'value', #3 '7' ], 'value' => '7' }, 'My::Param' )
bless( { 'key' => 'y', 'meta_info' => [ #0 'y=123' ], 'value' => '123' }, 'My:Param' )

Ответы [ 2 ]

10 голосов
/ 17 октября 2011

В этом случае уже изобретенное колесо называется URI

$ perl -MData::Dumper -MURI -e'
    $uri = URI->new("myhashkey?key1=val1&key2=val2&key3=val3&key4=val4");
    $h{ $uri->path } = { $uri->query_form };
    print Dumper(\%h);
'
3 голосов
/ 17 октября 2011

Хотя это будет работать (1):

my $str = "myhashkey?key1=val1&key2=val2&key3=val3&key4=val4";

my ($path,$data) = split /\?/, $str, 2;
my %h = (
         $path => {
             map {
                 split /=/, $_, 2
             } split /\&/, $data
         }
        );

use Data::Dumper;
print Dumper \%h;

Я думаю, что ваше возражение против использования URI является случаем преждевременной оптимизации.Если вы не знаете, что накладные расходы значительны, не переживайте.

(1) - ограничения включают в себя работу с такими вещами, как & внутри желаемого текста.При нормальных обстоятельствах, таких как URI, это обрабатывается с помощью% escape-последовательностей.Тем не менее, у меня нет кода, чтобы справиться с этим выше.Это не обязательно будет трудно добавить (еще одна карта), но это может легко сделать обслуживание кода намного дороже, чем просто использование URI напрямую и влечет за собой любые (возможно незначительные) накладные расходы, которые он может включать.

...