2009-06-10 10 views
5

मैं कभी कभी इस तरह एक हैश का उपयोग:'मौजूद' का उपयोग कर अतिरिक्त हैश लुकअप?

if(exists $ids{$name}){ 
    $id = $ids{$name}; 
} 

अच्छा अभ्यास है कि है? मैं थोड़ा चिंतित हूं कि इसमें दो लुकअप हैं जहां वास्तव में एक किया जाना चाहिए। क्या अस्तित्व की जांच करने और मूल्य असाइन करने का कोई बेहतर तरीका है?

उत्तर

10

exists साथ की जाँच करके किया गया था, आप autovivification को रोकने के। Autovivification : What is it and why do I care? देखें।

अद्यतन:trendels नीचे बताए गए अनुसार, आपके द्वारा पोस्ट किए गए उदाहरण में ऑटोविविफिकेशन नहीं खेलता है। मुझे लगता है कि वास्तविक कोड में बहु-स्तर हैंश शामिल हैं। अगर यह एक बहु स्तरीय हैश आप यह कर सकते हैं नहीं है

#!/usr/bin/perl 

use strict; 
use warnings; 

use Data::Dumper; 

my (%hash, $x); 

if (exists $hash{test}->{vivify}) { 
    $x = $hash{test}->{vivify}->{now}; 
} 

print Dumper \%hash; 

$x = $hash{test}->{vivify}->{now}; 

print Dumper \%hash; 

__END__ 


C:\Temp> t 
$VAR1 = { 
    'test' => {} 
}; 
$VAR1 = { 
    'test' => { 
     'vivify' => {} 
    } 
}; 
+1

वास्तव में मूल्य को पुनर्प्राप्त करने से सस्ता है? आखिरकार, जब टकराव पाता है तो उसे एक लिंक्ड सूची का पालन नहीं करना पड़ता है। – Frank

+1

इस विशेष मामले में, हालांकि, "$ name" के लिए हैश कुंजी * ऑटोविविफिकेशन द्वारा नहीं बनाई जाएगी। केवल एक कुंजी नेस्टेड एक स्तर गहराई तक पहुंचने का प्रयास कर रहा है, जैसे कि "$ id = $ ids {$ name} {other}" "$ name" कुंजी बनाएगा। – trendels

+0

@trendels सही लेकिन मुझे लगता है कि ओपी अधिक सरलीकृत था। फिर भी, मुझे यह इंगित करना चाहिए था। –

1

आप एक देखने इस तरह से यह कर सकते हैं:

$tmp = $ids{$name}; 
$id = $tmp if (defined $tmp); 

हालांकि, मैं परेशान नहीं होगा जब तक कि मैंने देखा है कि है कि एक टोंटी

+0

ठीक है, लेकिन यह वास्तव में बिल्कुल वही नहीं है। यदि कोई मान है (अनदेखा हो सकता है) चेक करता है, जबकि परिभाषित चेक होता है और कोई मान नहीं है और यह अनिश्चित नहीं है। – Frank

+0

आपके पास एक बिंदु है, लेकिन दिन के अंत में यदि यह अस्तित्व में नहीं है या यदि यह अस्तित्व में है लेकिन अपरिभाषित है, तो आपको एक अनिश्चितता मिल जाएगी। क्या आप यहां एक प्रदर्शन हिट देख रहे हैं कि आप इसके बारे में चिंतित हैं, या यह पूरी तरह अकादमिक है? मैं सिर्फ जिज्ञासा से पूछता हूं, और कुछ नहीं ... –

+1

शुद्ध रूप से अकादमिक! मुझे बस इस तथ्य को पसंद नहीं आया कि मैं दो बार हैश की जांच कर रहा हूं। मैं इसे बदल दूंगा और जैसा कि आपने सुझाव दिया है, बस एक 'परिभाषित' जांच करें। – Frank

0

:

यहाँ एक उदाहरण है

$id = $ids{$name} || 'foo'; 

या $ आईडी पहले से ही अपना महत्व होता है यदि:

$id ||= $ids{$name}; 

जहां 'foo' डिफ़ॉल्ट या गिरावट वाला मान है। यदि यह एक बहु-स्तर हैश है तो आप थ्रेड में पहले चर्चा की गई ऑटोविविफिकेशन से बचने के लिए 'मौजूद' का उपयोग करेंगे या अगर ऑटोविविफिकेशन कोई समस्या नहीं होने वाला है तो इसका उपयोग न करें।

+0

पी। कोई "धागे" नहीं हैं। प्रश्नों के उत्तर, उत्तर और प्रश्नों की टिप्पणियां हैं। कोई धागा नहीं –

+0

भी पीएस। कोई "पहले" नहीं है, "पुराना", "नया" और "वोट" टैब देखें जो आदेश को मैश करता है। –

+0

क्या होता है जब $ ids {$ name} 0 या खाली या अनिश्चित होता है? – innaM

1

आप हैश पर Hash::Util की लॉक_की लागू कर सकते हैं। फिर एक eval के भीतर अपने असाइनमेंट प्रदर्शन करते हैं।

my %h; 
for my $key (@some_vals) { 
    ... 
    $h{$key} = undef unless exists $h{$key}; 
    ... 
} 

return keys %h; 

इस कोड को थोड़ा आमतौर पर की तुलना में तेजी प्रयोग किया जाता है $h{$key}++:

#!/usr/bin/perl 
use Hash::Util qw/lock_keys/; 

my %a = (
    1 => 'one', 
    2 => 'two' 
); 

lock_keys(%a); 

eval {$val = $a{2}};  # this assignment completes 
eval {$val = $a{3}};  # this assignment aborts 
print "val=$val\n";  # has value 'two' 
0

अगर मैं उच्च प्रदर्शन चाहते हैं मैं इस मुहावरे लिखने के लिए जब चाहते सेट के रूप में हैश बनाने के लिए प्रयोग किया जाता रहा हूँ। exists बेकार असाइनमेंट से बचाता है और undef मूल्य के लिए आवंटन से बचाता है। आपके लिए सबसे अच्छा जवाब है: इसे बेंचमार्क करें! मुझे लगता है कि exists $ids{$name}$id=$ids{$name} से थोड़ा तेज़ है और यदि आपके पास बड़ा मिस अनुपात है तो आपका संस्करण मौजूद है, असाइनमेंट और परीक्षण के बाद तेज़ हो सकता है।

उदाहरण के लिए यदि मैं तेज़ सेट चौराहे चाहता हूं तो मैं ऐसा कुछ लिखूंगा।

sub intersect { 
    my $h; 
    @$h{@{shift()}} =(); 
    my $i; 
    for (@_) { 
    return unless %$h; 
    $i = {}; 
    @$i{grep exists $h->{$_}, @$_} =(); 
    $h = $i; 
    } 
    return keys %$h; 
} 
+1

ऐसी कुंजी बनाना जो पहले से ही हैश में नहीं हैं, आमतौर पर एक अच्छा विचार नहीं है। आप उन चाबियों को स्टोर करना शुरू नहीं करना चाहते हैं जिन्हें आप नहीं चाहते हैं। –

+0

आप गलत समझते हैं। दुबारा कोशिश कीजिये। –

+0

उस शब्द का अर्थ यह नहीं है कि इसका क्या अर्थ है। – Ether

0

प्रदर्शन इस मामले में महत्वपूर्ण नहीं है "डेवेल :: NYTProf"। लेकिन आपके सवाल का जवाब देने के लिए: अगर हैश में मूल्य मौजूद नहीं है

, "मौजूद है" बहुत तेजी से

if(exists $ids{$name}){ 
    $id = $ids{$name}; 
} 

है लेकिन अगर यह करने वाला दूसरा देखने किया जाता है मौजूद है। केवल एक ही स्वरूप को प्रभावी बनाने से मौजूद है, तो मूल्य की संभावना है हो जाएगा तेजी से

$id = $ids{$name}; 
if($id){ 
    #.... 
} 

एक पर्ल मेलिंग सूची से इस छोटे से बेंचमार्क देखते हैं।

#!/usr/bin/perl -w 
use strict; 
use Benchmark qw(timethese); 

use vars qw(%hash); 
@hash{ 'A' .. 'Z', 'a' .. 'z' } = (1) x 52; 

my $key = 'xx'; 
timethese 10000000, { 
     'defined' => sub { 
       if (defined $hash{$key}) { my $x = $hash{$key}; return $x; }; 
       return 0; 
     }, 
     'defined_smart' => sub { 
       my $x = $hash{$key}; 
       if (defined $x) { 
         return $x; 
       }; 
       return 0; 
     }, 
     'exists' => sub { 
       if (exists $hash{$key}) { my $x = $hash{$key}; return $x; }; 
       return 0; 
     }, 
     'as is' => sub { 
       if ($hash{$key}) { my $x = $hash{$key}; return $x; }; 
       return 0; 
     }, 
     'as is_smart' => sub { 
       my $x = $hash{$key}; 
       if ($x) { return $x; }; 
       return 0; 
     }, 

}; 

एक कुंजी ('xx') का उपयोग करके मौजूद नहीं है जो दिखाता है कि 'मौजूद' विजेता है।

Benchmark: timing 10000000 iterations of as is, as is_smart, defined, defined_smart, exists... 
    as is: 1 wallclock secs (1.52 usr + 0.00 sys = 1.52 CPU) @ 6578947.37/s (n=10000000) 
as is_smart: 3 wallclock secs (2.67 usr + 0.00 sys = 2.67 CPU) @ 3745318.35/s (n=10000000) 
    defined: 3 wallclock secs (1.53 usr + 0.00 sys = 1.53 CPU) @ 6535947.71/s (n=10000000) 
defined_smart: 3 wallclock secs (2.17 usr + 0.00 sys = 2.17 CPU) @ 4608294.93/s (n=10000000) 
    exists: 1 wallclock secs (1.33 usr + 0.00 sys = 1.33 CPU) @ 7518796.99/s (n=10000000) 

एक प्रमुख ('एक्स') है कि मौजूद है करता है का उपयोग कर पता चलता है कि 'is_smart' के रूप में विजेता है।

Benchmark: timing 10000000 iterations of as is, as is_smart, defined, defined_smart, exists... 
    as is: 3 wallclock secs (2.76 usr + 0.00 sys = 2.76 CPU) @ 3623188.41/s (n=10000000) 
as is_smart: 3 wallclock secs (1.81 usr + 0.00 sys = 1.81 CPU) @ 5524861.88/s (n=10000000) 
    defined: 3 wallclock secs (3.42 usr + 0.00 sys = 3.42 CPU) @ 2923976.61/s (n=10000000) 
defined_smart: 2 wallclock secs (2.32 usr + 0.00 sys = 2.32 CPU) @ 4310344.83/s (n=10000000) 
    exists: 3 wallclock secs (2.83 usr + 0.00 sys = 2.83 CPU) @ 3533568.90/s (n=10000000) 
संबंधित मुद्दे