2013-05-04 8 views
5

मेरे पास रेफरी के संबंध में यहां बहुत ही नोब-आश प्रश्न है, हालांकि अभी भी मुझे कम से कम परेशान कर रहा है ...
नीचे दिए गए कोड उदाहरण में, मैं एक हैश बनाने की कोशिश कर रहा हूं सरणियों:
पर्ल संदर्भों का सही तरीके से उपयोग कैसे करें

#!/usr/bin/perl 

use strict; 
use warnings; 
use 5.010; 
use Data::Dumper; 

$Data::Dumper::Sortkeys = 1; 
$Data::Dumper::Terse = 1; 
$Data::Dumper::Quotekeys = 0; 

my @a1 = ('a1', 1, 1, 1); 
my @a2 = ('a2', 2, 2, 2); 

my $a1_ref = \@a1; 
my $a2_ref = \@a2; 

my @a = ($a1_ref, $a2_ref); 

my %h =(); 

for my $i (1 .. 2) { 
     $h{"$i"} = \@a; 
} 

say Dumper \%h; 

डम्पर उत्पादन

{ 
      '1' => [ 
        [ 
        'a1', 
        1, 
        1, 
        1 
        ], 
        [ 
        'a2', 
        2, 
        2, 
        2 
        ] 
       ], 
      '2' => $VAR1->{'1'} 
     } 

सवाल यहाँ है:
क्यों $ ज है { '2'} एक $ के संदर्भ ज { '1'}? मैं @ ए सरणी-ऑफ-एरे के बने समान कुंजी-मानों के साथ हैश% h बनाने की कोशिश कर रहा हूं। मैं हैश के प्रत्येक कुंजी-मूल्य को @ ए के आधार पर अपना स्वयं का एओए रखना चाहता हूं, लेकिन मुझे इसके बजाय $ h {'1'} के संदर्भ मिल रहे हैं। मैं क्या गलत कर रहा हूं??
डम्पर उत्पादन मैं हासिल करने के लिए कोशिश कर रहा हूँ है:

{ 
      '1' => [ 
        [ 
        'a1', 
        1, 
        1, 
        1 
        ], 
        [ 
        'a2', 
        2, 
        2, 
        2 
        ] 
       ], 
      '2' => [ 
        [ 
        'a1', 
        1, 
        1, 
        1 
        ], 
        [ 
        'a2', 
        2, 
        2, 
        2 
        ] 
       ] 
     } 

किसी भी मदद की सराहना की। अग्रिम में धन्यवाद!
-dan

उत्तर

4

ऐसा नहीं है कि $h{'2'}$h{'1'} लिए एक संदर्भ है, लेकिन वह दोनों एक ही सरणी, अर्थात् @a के लिए संदर्भ नहीं है। क्या आप शायद चाहते हैं:

for my $i (1 .. 2) { 
    $h{"$i"} = $a[$i - 1]; 
} 

जो इस के बराबर है:

$h{'1'} = $a[0]; # i.e., $a1_ref 
$h{'2'} = $a[1]; # i.e., $a2_ref 

जो $h{'1'}@a1 और $h{'2'}@a2 के लिए एक संदर्भ के लिए एक संदर्भ बनाता है।

संयोग से, आप इसे उपयोगी गुमनाम सरणियों और हैश (क्रमशः) के लिए संदर्भ बनाने के लिए अंकन [ ... ] और { ... } उपयोग करने के लिए मिल सकती है। जब से तुम $a1_ref और $a2_ref के माध्यम से छोड़कर @a1 और @a2 का उपयोग कभी नहीं, आप के रूप में अच्छी बाद सीधे बना सकता है:

my $a1_ref = [ 'a1', 1, 1, 1 ]; # reference to a new array (no name needed) 
my $a2_ref = [ 'a2', 2, 2, 2 ]; # ditto 

संपादित अद्यतन प्रश्न के लिए: एक सरणी कॉपी करने के लिए, आप लिख सकते हैं:

my @orig = (1, 2, 3); 
my @new = @orig; 

या:

my $orig_ref = [1, 2, 3]; 
my $new_ref = [@$orig_ref]; # arrayref -> array -> list -> array -> arrayref 

आपके मामले में, यदि मैं आपको सही तरीके से समझता हूं, तो आपको थोड़ा "गहरी" प्रतिलिपि करने की आवश्यकता है: आप केवल दो तत्वों को एक ही तत्व के साथ नहीं चाहते हैं, आप दो सरणी चाहते हैं जिनके तत्व अलग-अलग सरणी के संदर्भ हैं एक ही तत्वकोई अंतर्निहित है पर्ल तरीका है कि ऐसा करने के लिए, लेकिन आप एक पाश लिख सकते हैं, या का उपयोग map समारोह:

my @orig = ([1, 2, 3], [4, 5, 6]); 
my @new = map [@$_], @orig; 

तो:

for my $i (1 .. 2) { 
    $h{"$i"} = [map [@$_], @a]; 
} 
+0

धन्यवाद @ruakh, लेकिन है कि मैं वास्तव में क्या हासिल करने के लिए कोशिश कर रहा था नहीं है। मैंने अपनी पोस्ट को और जानकारी के साथ अपडेट किया है। संदर्भ संदर्भों के संबंध में यह एक अच्छी युक्ति है। – Gnowl

2

यह (तुम क्या कर रहे) $h{1} कर देगा और $h{2}, एक ही सरणी का उल्लेख @a:

for my $i (1 .. 2) { 
     $h{"$i"} = \@a; 
    } 

यह कर देगा $h{1} और $h{2} दो अलग-अलग वस्तुओं को देखें, हर एक की जा रही @a की एक प्रति:

for my $i (1 .. 2) { 
     $h{"$i"} = [ @a ]; 
    } 

लेकिन भीतरी सरणियों अभी भी एलियास की जाएगी।

2

मैं इस कोड आप क्या चाहते हैं करता है लगता है: यह है कि आपके पास गहरी प्रतिलिपि चाहते लगता है।

मैं Data::Dump में बदला गया है क्योंकि मैं इसके उत्पादन पसंद करते हैं।

डेटा का संदर्भ लेने में समस्या यह है कि इससे कोई फर्क नहीं पड़ता कि आप उस संदर्भ को कितनी बार कॉपी करते हैं, फिर भी यह एक ही डेटा को इंगित करता है, इसलिए उस डेटा में परिवर्तन हर जगह इसका चयन किया जाता है।

की, कहते हैं, एक सरणी एक दूसरे, स्वतंत्र प्रतिलिपि बनाने के लिए, आप निश्चित रूप से my @copy = @array और काम लिख सकते हैं वहाँ से। लेकिन यह एक नई अज्ञात सरणी [ @array ] जो प्रतियां सरणी की सामग्री का उपयोग करने के लिए सुविधाजनक है और इसे करने के लिए एक संदर्भ देता है।

आप प्रत्येक हैश मान को दो-तत्व सरणी का संदर्भ मानना ​​चाहते हैं, जिनमें से प्रत्येक @a1 और @a2 से डेटा वाले किसी अन्य सरणी का संदर्भ है। यह कोड आपके लिए ऐसा करेगा।

एक और मुद्दा यह है कि, के बाद से हैश कुंजी तार कर रहे हैं, यह उनके लिए सांख्यिक मानों का उपयोग करने के असामान्य है है: यह इंगित करता है कि आप एक सरणी के बजाय का उपयोग करना चाहिए। लेकिन चूंकि यह सब स्पष्ट रूप से प्लेसहोल्डर डेटा है, इसलिए मैं इसके बारे में बहुत चिंतित नहीं हूं।

use strict; 
use warnings; 

use Data::Dump; 

my @a1 = qw/ a1 1 1 1 /; 
my @a2 = qw/ a2 2 2 2 /; 

my %h; 

for my $i (1, 2) { 
    $h{$i} = [ [ @a1 ], [ @a2 ] ]; 
} 

dd \%h; 

उत्पादन

{ 
    1 => [["a1", 1, 1, 1], ["a2", 2, 2, 2]], 
    2 => [["a1", 1, 1, 1], ["a2", 2, 2, 2]], 
} 
0

सभी उत्तरों ऊपर मुझे सही समाधान (और इस मुद्दे) की ओर इशारा किया। और संरचना की एक प्रति बनाने की आवश्यकता है और फिर इसके संदर्भ का उपयोग करें। यहां दिए गए सरणी और हैंश ने एक और जटिल संरचना के लिए प्लेसहोल्डर था। तो संरचना मैं Clone मॉड्यूल है, जो वास्तव में एक संरचना की गहरी प्रतिलिपि करता है इस्तेमाल किया की एक प्रतिलिपि बनाने और इसे करने के लिए एक अलग संदर्भ वापस जाने के लिए। सभी उत्तर के लिए धन्यवाद!

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