2012-01-13 14 views
-3

私はそれを最適化する方法やこれを行う良い方法があるかどうかを知るために作成した関数を皆さんと共有したいと思っていました。キーと値のペアのハッシュをどのように平坦化しますか?

sub flatten{ 
    my($ref,$delim,$item_delim,$array,$str) = @_; 

    die("Required Hash Reference") unless isHash($ref); 

    $delim = $delim ? $delim :'_'; 

     #dump into array hash vals #simplified 
     if(!$item_delim){ 
     @{$array} = %{$ref}; 
     }else{ 
     my($keys,$values); 

     $keys = getKeys($ref); 
     $values = getValues($ref); 

     #item strings 
     if($#$keys > 0 && $#$values > 0){ 
      #fix for issue where value[n] is empty 
      @{$array}= map{ (defined $$values[ $_ ]) ? $$keys[ $_ ].$item_delim.$$values[ $_ ] : $$keys[ $_ ].$item_delim } 0 .. int($#$keys); 
     }else{ 
     log "No Values to flatten"; 
     return ''; 
     } 
     } 

    $str = join($delim,@{$array}); 
    return $str; 
    } 

ここで注意する必要がある最適化点はありますか?

は基本的に私は

モジュールなしのソリューションは、私が実際には効果的にハッシュを平坦にする方法を知りたいことが好ましい

を更新し$STRING= key1=val1&key2=val2 ...

$HASH => { 

key1 => 'val1', 
key2 => 'val2', 
key3 => 'val3', 

} 

から行ってみたいです!

ここでの関数の中には、単純に彼らが言うことを行うラッパー関数であることに注意してください。 isHash getKeys ...それらには注意を払わないでください!

+2

なぜisHash'、 'getKeys'、' getValues'のような関数を使用していますか?これは企業標準の一部ですか?また、参照の代わりに単純な配列やハッシュを使用することはできませんか? – Borodin

答えて

3

my $hashref = {  
    key1 => 'val1', 
    key2 => 'val2', 
    key3 => 'val3', 
}; 

sub encode { 
    my $str = shift; 
    $str =~ s/([^A-Za-z0-9\.\/\_\-])/sprintf("%%%02X", ord($1))/seg; 
    return $str; 
} 

my $str = join '&' => map { encode($_).'='.encode($hashref->{$_}) } grep { defined $hashref->{$_} } keys %$hashref; 

結果:

key2=val2&key1=val1&key3=val3 
0
use URI::Escape; 
my $str=join '&',map {uri_escape($_).'='.uri_escape($QUERY_STRING->{$_})} grep {defined $QUERY_STRING->{$_}} keys %$QUERY_STRING; 

これはうまくいくはずです。

+0

エスケープがありません。あなたのキーまたは値に[かなり長いリスト](https://metacpan.org/module/URI::Escape)の文字が含まれていると、これは爆発します。 – hobbs

+0

@ hobbs、ありがとう!ありがとう! – cirne100

+0

@nodebunny、モジュールなしでそれをするには、正規表現を使ってすべての安全でない文字とマッチさせ、それを表す16進数で置き換えます!/sprintf( "%02X"、ord $ 1)/ eg;このような(または非常に近い)s /([^ [\ w - \。\〜]]) – cirne100

6

便利な方法の1つは、URIquery_form機能を使用することです。

use URI; 

my $uri = URI->new("", "http"); # We don't actually care about the path... 
$uri->query_form(%params); 
my $query_string = $uri->query; 

別の、より多くのマニュアルの方法は、単にURI::Escape、マップを使用し、参加することです。モジュールなし

+2

@nodebunnyあなたが奇妙な制限の下で働いているなら、あなたはあなたの質問に言及すべきです。モジュールを使用するつもりがない場合は、http://search.cpan.org/perldoc?URIにアクセスし、ソースを参照して必要なものを取り出します。 – TLP

+1

@nodebunny「平坦化」という言葉が何を意味するのかわからないようです。 perlでハッシュを平坦化する方法は '@kv =%hash'です。 – hobbs

3

私はあなたのサブルーチンが任意のより複雑にする必要があることを意味あなたの質問には何も見ることができない以上:

sub flatten { 
    my ($hash, $delim, $item_delim) = @_; 

    $delim //= '&', 
    $item_delim //= '='; 

    return join $delim, map { "$_$item_delim$hash->{$_}" } keys %$hash; 
} 

更新:ここにいくつかの下書きを取得します。私は、人々が私が何かをURIエンコーディングしていないという事実に反対すると仮定します。元の質問にURIを構築することは何もないことを指摘します。もし私がそれを知っていたら、私は確かにappropriate moduleを使うでしょう。

これは私が「私はあなたの質問に何も見ることができません...」と言った理由です。

関連する問題