copying hashes without references

J

jere

After getting a good grasp on references (or at least i thought). I ran
into a simple problem which i cannot seem to get away from.

I have a complex data structure of hashes / arrays that I am setting up
before running a program. I noticed that several of the documents I
was parsing with this program shared the same attributes. I am using
the data structure as a guide - it tells me what to parse (and what not
to parse). Therefore, I need an element for each page i want to
parse, but i dont want to have to type the same attributes over and
over again. I created a hash with the common attributes and tried to
simply insert it into the hash. I might have several of these
"templates", so I created a hash to store them.

#here is hash (im going to try to insert
# %{ $fmt_template{outsrc_1}:

%fmt_template =
( 'outsrc_1' => {
System => 'end_sides',
DataRange => [ { R => 8, C => 0, r => 999, c => 3 },
{ R => 8, C => 5, r => 999, c => 8 } ],
Columns => [ 'sn', 'sn_net', 'host', 'desc' ]
}
);


# Here is a snippet of the array im trying to insert into:

%format = ( 'format_e' => {
Sheet => [
#Sheet 0: sheet name
{ System => 'step',
DataRange => [ { R => 2, C => 2, r => 41, c => 4 } ],
Columns => [ 'step', 'step2', 'step3' ]
}
#Sheet 1-4: these sheets are all the same and share similar
# attributes:
%format->{'format_excel'},
%format->{'format_excel'},
%format->{'format_excel'},
%format->{'format_excel'}
]
}
);

#so im on a particular sheet and i know its number, so i do:
#for loop for each Sheet (index via $i)
my $Fmt = $format{'format_e'}{Sheet}[$i];

#well, then i realized that there is one attribute that needed
#to be adjusted between the differnt sheets
#notice that the inserted hash has a r = 999. This represents max
#number of rows i could have, but i need to find the specific max #rows
of each document and compare. So i do the following:

#$x iterates through the number of DataRange arrays each
#Sheet[$i] contains:
if ( $Fmt->{DataRange}[$x]->{r} > $oSheet->{MaxRow} ) {
$Fmt->{DataRange}[$x]->{r} = $oSheet->{MaxRow};
}

#now ive changed the individual data range maxrow (r) element
# not true! ive changed them all due to using references??
# during the next for loop (next sheet) $Fmt->{DataRange}[$x]->{r}
# = 40 (maxrow of the previous sheet). It should be 999 again.

#Can someone point out what im doing wrong? I tried turning
#%format into a reference using $format = { hash } notation and #then
using {} braces arround "$format->{format_e}" in the larger
#hash. This works sytactically, but still when i change one, i
#change them all.

#I thought using a reference and THEN using a dereference would
#return a copy of each but that didnt work. I also tried just for
#fun the following

%format1 = %format
%format2 = %format

#and then tried using them in the code (references and not), but
#that still suffered from the same problem - it all seemed to be
#copies of the same memory location so when i changed one thing,
#they all changed.

#I even tried writing a small test program to test out different
#sytnaxes until i found something that worked, but this was
#fruitless.
 
I

ioneabu

#here is hash (im going to try to insert
# %{ $fmt_template{outsrc_1}:

%fmt_template =
( 'outsrc_1' => {
System => 'end_sides',
DataRange => [ { R => 8, C => 0, r => 999, c => 3 },
{ R => 8, C => 5, r => 999, c => 8 } ],
Columns => [ 'sn', 'sn_net', 'host', 'desc' ]
}
);

a hash with a single element which is a reference to hash which
contains three elements: first contains a string, second contains an
array reference in which there is two hash references, and third is
another array reference with four strings in the array.
# Here is a snippet of the array im trying to insert into:

%format = ( 'format_e' => {
Sheet => [
#Sheet 0: sheet name
{ System => 'step',
DataRange => [ { R => 2, C => 2, r => 41, c => 4 } ],
Columns => [ 'step', 'step2', 'step3' ]
}
#Sheet 1-4: these sheets are all the same and share similar
# attributes:
%format->{'format_excel'},
%format->{'format_excel'},
%format->{'format_excel'},
%format->{'format_excel'}
]
}
);

#so im on a particular sheet and i know its number, so i do:
#for loop for each Sheet (index via $i)
my $Fmt = $format{'format_e'}{Sheet}[$i];

I think there is a problem here with how you dereference.

my $Fmt = ${${$format{'format_e'}}{sheet}}[$i];

or

my $Fmt = $format{'format_e'}->{Sheet}->[$i];
#well, then i realized that there is one attribute that needed
#to be adjusted between the differnt sheets
#notice that the inserted hash has a r = 999. This represents max
#number of rows i could have, but i need to find the specific max #rows
of each document and compare. So i do the following:

#$x iterates through the number of DataRange arrays each
#Sheet[$i] contains:
if ( $Fmt->{DataRange}[$x]->{r} > $oSheet->{MaxRow} ) {
$Fmt->{DataRange}[$x]->{r} = $oSheet->{MaxRow};
}
$Fmt->{DataRange}->[$x]->{r}


#now ive changed the individual data range maxrow (r) element
# not true! ive changed them all due to using references??
# during the next for loop (next sheet) $Fmt->{DataRange}[$x]->{r}
# = 40 (maxrow of the previous sheet). It should be 999 again.

#Can someone point out what im doing wrong? I tried turning
#%format into a reference using $format = { hash } notation and #then
using {} braces arround "$format->{format_e}" in the larger
#hash. This works sytactically, but still when i change one, i
#change them all.

#I thought using a reference and THEN using a dereference would
#return a copy of each but that didnt work. I also tried just for
#fun the following

%format1 = %format
%format2 = %format

#and then tried using them in the code (references and not), but
#that still suffered from the same problem - it all seemed to be
#copies of the same memory location so when i changed one thing,
#they all changed.

#I even tried writing a small test program to test out different
#sytnaxes until i found something that worked, but this was
#fruitless.

I may be wrong on those, but it looks like that is the problem or part
of the problem. It's hard to believe that you need such a complicated
structure, but maybe you do.

wana
 
T

Tad McClellan

Subject: copying hashes without references ^^^^
After getting a good grasp on references (or at least i thought). I ran
into a simple problem


Perhaps someone else has run into the same problem before?

It may even have happened so often that a pat answer has been
written up and widely published.

Collections of such problems, and their solutions, are known
as FAQs (Frequently Asked Questions).

You should consult the FAQs for a particular subject area when
you encounter a problem in that area.

The FAQs for Perl come with the perl distribution, they are
sitting there on your hard drive somewhere waiting for you
to look at them. :)

which i cannot seem to get away from.


perldoc -q copy

How do I print out or copy a recursive data structure?
 
J

jere

Hi,

what you do in your example is work with "shallow copies" of your
data. If you want to really copy the contents of a data structure
instead of the references it contains, this is called a "deep copy".
Randal L. Schwartz has written an good article for the Unix Review
on that topic:
http://www.stonehenge.com/merlyn/UnixReview/col30.html

Also CPAN holds a bunch of cloning modules, just give "clone" as
search term to search.cpan.org.

HTH
-Chris

Chris,
Thank you very much for this article! I used the FAQ ( i knew I'd
get some RTFM or RTFFAQ replies even if i didnt) and didnt realize the
terminology of "deep" and "shallow" copies. Also, I thought it would
be trivial to do what I was asking --- that it was just some part of
PERL syntax that i was missing and wasnt able to figure out. This
article was a great resource. Thanks again!
-Jere
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top