perl छपाई के दौरान हैश कुंजियों के अलग-अलग क्रम क्यों हैं?




sorting data-structures (3)

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

पर्ल में कम से कम एक दशक के हैंश के लिए प्रमुख ऑर्डर की गारंटी नहीं है हाल ही में, हैश रेडमाइजेशन एक सामान्य सुरक्षा "सख्त" प्रयास का हिस्सा रहा है हैश को यादृच्छिक होने के अच्छे कारण हैं। अधिक जानकारी के लिए एल्गोरिथम जटिलता के हमले की perlsec चर्चा देखें। आप पर्ल सुरक्षा दस्तावेज में ध्यान देंगे कि अतिरिक्त संवर्द्धन perl-5.18 में जोड़े गए थे - यदि आप पिछले संस्करणों की तुलना में एक अलग व्यवहार देख रहे हैं तो यह हाल के परिवर्तनों के कारण हो सकता है

स्पष्ट रूप से अपने हैश कुंजी को एक नियतात्मक तरीके से सॉर्ट करने के अलावा, आपके पास आपके हैशों को क्रम देने के लिए अन्य तरीकों से भी हो सकते हैं: Hash::Ordered ऑर्डर Hash::Ordered एक उदाहरण है। Hash::Ordered दस्तावेज़ों में कई अन्य मॉड्यूल के पेशेवरों और विपक्षों की अच्छी चर्चा है।

जबकि एक हैश कुंजी-मूल्य जोड़े में व्यवस्थित स्केलेरों की " अनारक्षित टोकरी " है; एक सरणी स्केलर का एक " अनुक्रमित अनुक्रम " है [ 1 ] एक " टुकड़ा " एक सूची के कई तत्वों, एक सरणी या एक साथ एक हैश तक पहुंचने का तरीका है। एक टुकड़ा @ सिगिल का उपयोग करता है, क्योंकि ऑपरेशन कई मानों की सूची देता है - और @ साथ हम "क्रम अनुक्रम" प्राप्त करते हैं। इसका नतीजा यह है कि एक प्रकार का "आदेश" एक हैश पर लगाने का एक तरीका यह है कि इसे एक्सेस करने के लिए एक टुकड़ा का उपयोग किया जा रहा है:

# We want alphabetical disorder ...
my %hashed = ( 1 => "z", 2 => "x", 3 => "y" );
for my $key ( keys %hashed ) { print $hashed{$key} } ;
__END__    
zyx

हम चाहते हैं " zxy " नहीं " zyx " इस हैश पर ऑर्डर के हमारे मनमानी संस्करण को लागू करने के लिए हमें सबसे पहले यह समझना होगा कि यहां अपराधी की keys %hashed जो चाबियाँ यादृच्छिक क्रम में देता है। इसका समाधान सीसीएस की कुंजी को sort करने के लिए है और इस उत्तरदायी उदाहरण में हम उन्हें @sort_order में संग्रहीत करते हैं और इसे हैश से हम क्या चाहते हैं, इसे "टुकड़ा" करने के लिए उपयोग करें, जिस तरह से हम चाहते हैं:

my @sort_order = sort keys %hashed ;
print @hashed{@sort_order} ;
__END__
zxy

टाडा !! जब आप एक हैश में कुंजी और मूल्यों को संग्रहीत करना चाहते हैं, लेकिन उस डेटा को क्रमबद्ध तरीके से एक्सेस करने के लिए स्लाइस उपयोगी हो सकते हैं। जब आप एक हैश टुकड़ा करना चाहते हैं, तो " @ " को याद रखें; के रूप में perldata यह डालता है: "आप एक '@' ... एक हैश टुकड़े पर ... का उपयोग करें [क्योंकि] तुम वापस हो रही है ... एक सूची" और सूचियां व्यवस्थित हैं

[ 1 ] हैश की परिभाषा "अनारक्षित बास्केट" के रूप में और "क्रमबद्ध अनुक्रम" के रूप में सरणियों के रूप में हैं, पर्ल में एरेज़ बनाम सूची पर माइक फ्रिडमैन (एफआईआईडीईओ) का उत्कृष्ट लेख है।

आगे के संदर्भ

मैं एक ही कुंजी का उपयोग करके कई हैशों का निर्माण करना चाहता हूं और जब मैं उन्हें मुद्रित करता हूं, तो उसी क्रम के लिए कुंजी का उपयोग करना चाहते हैं। इसलिए, नीचे दिए गए उदाहरण में, $hash1 और $hash2 की चाबियाँ हमेशा एक ही ऑर्डर चाहिए, लेकिन हैश बनाने के दौरान उस आदेश को रखने की कोई आवश्यकता नहीं होनी चाहिए।

use Data::Dumper;

my $hash1 = {
  keyc => 2,
  key1 => 1,
  keya => 3,
  keyb => 4,
};

my $hash2 = {
  keyc => 2,
  key1 => 1,
  keya => 3,
  keyb => 4,
};

print Dumper $hash1, $hash2;

लेकिन उत्पादन निम्नानुसार है:

$VAR1 = {
          'key1' => 1,
          'keyc' => 2,
          'keyb' => 4,
          'keya' => 3
        };
$VAR2 = {
          'keyb' => 4,
          'keya' => 3,
          'keyc' => 2,
          'key1' => 1
        };

यानी हैश का एक अलग और अप्रत्याशित आदेश है। मेरे पर्ल के साथ क्या हुआ है?

मेरा पर्ल संस्करण है:

This is perl 5, version 18, subversion 2 (v5.18.2) built for darwin-thread-multi-2level
(with 2 registered patches, see perl -V for more detail)

सूचना: मुझे पता है कि पर्ल हैश की कुंजी क्रमबद्ध आदेश है मैं चाहता हूं कि उनके पास एक ही आदेश है, लेकिन सॉर्ट क्रम की आवश्यकता नहीं होनी चाहिए। मुझे उम्मीद है कि अगर मैं कोड फिर से चलाऊँगा तो मैं उसी मुद्रण आउटपुट प्राप्त कर सकता हूँ

उत्तर से सलाह के बाद, मैं दो पर्यावरण चर सेट:

PERL_HASH_SEED=0x00 PERL_PERTURB_KEYS=0

तब मैं उसी आउटपुट को प्राप्त कर सकता हूं जब मैं बार-बार कोड चलाऊंगा


आपके पर्ल के साथ कुछ भी गलत नहीं है, एक हैश बिना व्यवस्थित क्रमबद्ध है

यदि आप कुंजी से सॉर्ट करना चाहते हैं तो आपको ऐसा कुछ करने की आवश्यकता है:

foreach my $key (sort keys %hash1) {
    print $key, $hash1{$key};
}

और हैश 2 के लिए यही बात ...


जी। सीटो का उत्तर सही है। यदि आप डेटा :: डम्पर से क्रमबद्ध आउटपुट चाहते हैं, तो आप ऐसा कर सकते हैं:

use Data::Dumper;

my $hash1 = {
  keyc => 2,
  key1 => 1,
  keya => 3,
  keyb => 4,
};

my $hash2 = {
  keyc => 2,
  key1 => 1,
  keya => 3,
  keyb => 4,
};

my $dumper = Data::Dumper->new([$hash1, $hash2]);
$dumper->Sortkeys(1);
print $dumper->Dump;