मैं each
उपयोग कर रहा हूँ एक पर्ल हैश के माध्यम से पुनरावृति करने के लिए:क्या मैं अपने "प्रत्येक" इटरेटर को रीसेट किए बिना हैश कॉपी कर सकता हूं?
while (my ($key,$val) = each %hash) {
...
}
फिर कुछ दिलचस्प होता है और मैं हैश प्रिंट आउट करना चाहते हैं। पहले तो मुझे कुछ पर विचार करें:
while (my ($key,$val) = each %hash) {
if (something_interesting_happens()) {
foreach my $k (keys %hash) { print "$k => $hash{$k}\n" }
}
}
लेकिन वह काम नहीं करेगा, क्योंकि हर कोई जानता है कि एक हैश पर keys
(या values
) बुला आंतरिक each
के लिए इस्तेमाल किया इटरेटर रीसेट करता है, और हम एक अनंत लूप मिल सकता है। उदाहरण के लिए, ये स्क्रिप्ट हमेशा के लिए चलेगी:
perl -e '%a=(foo=>1); while(each %a){keys %a}'
perl -e '%a=(foo=>1); while(each %a){values %a}'
कोई समस्या नहीं, मैंने सोचा। मैं हैश की एक प्रति बना सकता हूं, और प्रतिलिपि मुद्रित कर सकता हूं।
if (something_interesting_happens()) {
%hash2 = %hash;
foreach my $k (keys %hash2) { print "$k => $hash2{$k}\n" }
}
लेकिन वह काम नहीं करता है, या तो। यह each
इटरेटर को भी रीसेट करता है। वास्तव में, किसी सूची संदर्भ में %hash
का कोई भी उपयोग अपने each
इटरेटर को रीसेट करने लगता है। तो ये हमेशा के लिए दौड़ते हैं:
perl -e '%a=(foo=>1); while(each %a){%b = %a}'
perl -e '%a=(foo=>1); while(each %a){@b = %a}'
perl -e '%a=(foo=>1); while(each %a){print %a}'
क्या यह कहीं भी दस्तावेज है? यह समझ में आता है कि एक हैश की सामग्री को रिटर्न स्टैक पर धक्का देने के लिए पर्ल को एक ही आंतरिक इटरेटर का उपयोग करने की आवश्यकता हो सकती है, लेकिन मैं हैश कार्यान्वयन की भी कल्पना कर सकता हूं जिसे ऐसा करने की आवश्यकता नहीं थी।
अधिक महत्वपूर्ण बात यह है कि क्या मैं चाहता हूं कि ऐसा करने का कोई तरीका है? each
इटरेटर को रीसेट किए बिना हैश के सभी तत्वों को प्राप्त करने के लिए?
यह भी पता चलता है कि आप एक each
यात्रा के अंदर एक हैश डिबग नहीं कर सकते हैं, या तो। पर डिबगर चलाने पर विचार करें:
%a = (foo => 123, bar => 456);
while (($k,$v) = each %a) {
$DB::single = 1;
$o .= "$k,$v;";
}
print $o;
बस हैश जहां डिबगर बंद हो जाता है (जैसे कि, p %a
या x %a
टाइपिंग) का निरीक्षण करके, आप कार्यक्रम के उत्पादन में बदल जाएगा।
अद्यतन: मैं इस समस्या का एक सामान्य समाधान के रूप में Hash::SafeKeys
अपलोड की गई। मुझे सही दिशा में इंगित करने के लिए @gpojd धन्यवाद और एक सुझाव के लिए @cjm जिसने समाधान को अधिक सरल बना दिया।
हाल ही में एक ही समस्या का सामना किया। पता चला है कि हैश :: सेफकीज़ बहुत धीमी है और हैश आकार पर निर्भर करता है, और हैश :: स्टोर्ड इटरेटर + डिफ़ॉल्ट कुंजी बहुत बेहतर प्रदर्शन करती है। –
@AlexandrEvstigneev - धन्यवाद, यह बहुत दिलचस्प है। मैं 'हैश :: सेफकीज़' – mob