2009-08-11 10 views
16

निम्न स्निपेट किसी सरणी में किसी मान की पहली घटना के सूचकांक की खोज करता है। हालांकि, जब $ इंडेक्स के आसपास कोष्ठक हटा दिया जाता है, तो यह सही तरीके से कार्य नहीं करता है। मैं क्या गलत कर रहा हूं?मेरा पर्ल grep पहला मैच क्यों नहीं लौटाता है?

my ($index) = grep { $array[$_] eq $search_for } 0..$#array; 

उत्तर

39

कोष्ठकों संदर्भ में grep संदर्भ सूची अदिश संदर्भ से मूल्यांकन किया जाता है बदल जाते हैं। स्केलर संदर्भ में grep अभिव्यक्ति सत्य होने की संख्या लौटाता है। सूची संदर्भ में यह उन तत्वों को लौटाता है जिनके लिए अभिव्यक्ति सत्य थी।

निम्नलिखित प्रकाश डाला संदर्भ का अंतर होता है:

my $x = grep {/foo/} @array; # the number of things that match /foo/ 
my ($x) = grep {/foo/} @array; # the first thing that matches /foo/ 
my @foo = grep {/foo/} @array; # all the things that match /foo/ 
my (@foo) = grep {/foo/} @array; # all the things that match /foo/ 
+0

'scalar @ array'' array ' –

1

grep एक सूची देता है। जब आप स्केलर वैरिएबल नाम को ब्रांड्स के अंदर डालते हैं, तो पर्ल उस पूरे एल-वैल्यू को एक सूची के रूप में मानता है, इसलिए यह उस चर में सूची में पहला मान निर्दिष्ट करता है।

आप कोष्ठक में अन्य scalars था, तो आप उन्हें में grep की वापसी सरणी से दूसरी, तीसरी, आदि मूल्यों को प्राप्त चाहते हैं:

my ($index, $foo, $bar) = grep { $array[$_] eq $search_for } 0..$#array; 
+3

grep में तत्वों की संख्या एक सरणी देता है। लेकिन केवल सरणी संदर्भ में। – innaM

+0

और स्केलर संदर्भ में यह मैच लौटने की संख्या को वापस लौटाता है, इसलिए वास्तव में इससे कोई फर्क नहीं पड़ता कि सरणी का आकार क्या है। – Plutor

+1

@Plutor: दस्तावेज़ स्पष्ट रूप से कहते हैं कि 'grep' क्या करता है इसलिए गलत वर्णन पोस्ट करने के लिए कोई औचित्य नहीं है। –

8

कोष्ठकों grep के लिए एक list context प्रदान करते हैं। grep वास्तव में उन तत्वों की सूची लौटाएगा जिनके लिए अभिव्यक्ति सत्य थी और न केवल अभिव्यक्ति के सत्य की संख्या।

+0

एस/सरणी संदर्भ/सूची संदर्भ/ –

+0

बेहतर तरीका। धन्यवाद। – innaM

+0

आपका स्वागत है। –

7

मुझे लगता है कि आप List::MoreUtils से first_index लिए देख रहे हैं:

use List::MoreUtils qw(first_index); 

# ... 

my $index = first_index { $_ eq $search_for } @array; 
5

ग्रेप समारोह सूची के संदर्भ और अदिश संदर्भ में अलग ढंग से व्यवहार करता है। यह perldoc -f grep में प्रलेखित:

सूची के प्रत्येक तत्व (स्थानीय रूप से प्रत्येक तत्व के लिए $ _ की स्थापना) के लिए ब्लॉक या EXPR का मूल्यांकन करता है और सूची मूल्य उन तत्वों जिसके लिए अभिव्यक्ति सच के लिए मूल्यांकन से मिलकर लौट जाता है। स्केलर संदर्भ में, अभिव्यक्ति की संख्या सही होती है।

आप खराब नामित wantarray समारोह के साथ अपने दम पर इस नकल कर सकते हैं:, मैं ग्रेप का उपयोग कर लगता है कि

sub my_grep { 
    my $sub = shift; 
    my @return; 
    for my $item (@_) { 
     push @return if $sub->($item); 
    } 
    return @return if wantarray; 
    return scalar @return; 
} 
1

इसके अलावा सिर्फ पहला उदाहरण खोजने के लिए एक छोटे से अक्षम है, क्योंकि यह अभी भी के माध्यम से चलने के लिए है और सरणी के प्रत्येक तत्व पर कॉलबैक चलाएं। विशेष रूप से यदि आपकी सरणी लंबी है, तो आप उपरोक्त वर्णित सूची :: MoreUtils का उपयोग करके लूप लिखना बेहतर कर सकते हैं या अन्यथा।

संबंधित मुद्दे