2012-01-13 5 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

하나의 편리한 방법은 URI 님의 query_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 "납작하게"라는 단어가 무슨 뜻인지 아는 것 같지 않습니다. 펄에서 해시를 평평하게 만드는 방법은'@kv = % hash'입니다. – hobbs

3

나는 당신의 서브 루틴이 더 이상 복잡 할 필요가 있음을 의미합니다 귀하의 질문에 아무것도 볼 수있는 것보다 :

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

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

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

업데이트 : 여기에 몇 개의 downvotes 얻기. 사람들이 내가 URI 인코딩을하지 않는다는 사실에 반대한다고 가정합니다. 나는 우리가 URI를 작성하고 있다는 원래의 질문에는 아무것도 없다는 것을 지적 할 것이다. 우리가 그렇다는 것을 알았다면 확실하게 appropriate module을 사용할 것입니다.

내가 "나는 당신의 질문에 아무것도 볼 수 없다"고 말한 이유입니다.

관련 문제