Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Wanet Telecoms Ltd on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

trying to turn my hashes into strings 3

Status
Not open for further replies.

darkreaper00

Technical User
Aug 5, 2002
23
US
Hey everyone--

I have an array of hashes that I want to turn into a collection of strings with the keys as their names and the values conserved. (so that in lots and lots of code i can type
Code:
$key
instead of
Code:
$array_name[$h]{key}
).

This was the first test program I made, and it was successful:

Code:
%hash = ( 	one => "abc",
			  two => "def",
			  three => "ghi",
		);

while (($key, $value) = each (%hash))
	{	print "\$key = $key, \$value = $value\n";
		 ${$key} = $value;
	}

print "\$one = $one, \$two = $two, \$three = $three\n";

The strings $one, $two, and $three contain the values assigned to them in the hash. Faced with this success, I decided to go ahead and make a subroutine out of it, that I could call from throughout my program as the need arose. This is where I ran into all sorts of problems, as I can't seem to figure out how to elegantly persuade perl to take my hash as an argument for the subroutine. I tried lots of different things, and none of them worked, but I'll show you one so you can see my thought process:

Code:
@hit = ( {	one => "abc",
			  two => "def",
			  three => "ghi",
		 },
		 {	four => "jkl",
		 	 five => "mno",
		 	 six => "pqr",
	 	 },
	);

dehash (%hit[1]);

print "\$one = $one, \$two = $two, \$three = $three\n";
print "\$four = $four, \$five = $five, \$six = $six\n";

sub dehash {
	%hash = @_;
	while (($key, $value) = each (%hash))
		{ ${$key} = $value;	}
}

I played with
Code:
each
, @ and $ in place of % in various spots, but remain thoroughly stumped. Is there a simple way to use my snippet as a subroutine, or, is there a simpler way to do what I'm trying to do that I've missed?

Thanks a bunch,
t
 
You need to call the subroutine as
Code:
dehash ( %{$hit[1]} );

jaa
 
more on that ...

Code:
$hit[i]
is a reference to a hash (if you print it out you will see something like [tt]HASH(0x81006e8)[/tt]. You de-reference a hash by using [tt]%{ }[/tt].

jaa
 
Dark Reaper,


NOTE for inexperienced programmers:
This thread uses symbolic references. Symbolic references are frowned upon by many programmers. Inexperienced programmers should avoid the use of symbolic references.


It would be faster to call dehash with a reference:
Code:
dehash( $hit[1] );

sub dehash {
    my $hash = shift;
    while ( my ($key, $value) = each %$hash ) {
        ${$key} = $value;
    }
}

HTH,

Charles
 
Thanks for your help -- I've got it working. There are, however, still some things I don't understand:

- why (&when) perl insists on having spaces inside parentheses
- what makes a symbolic reference faster and why i should avoid using them

I am quite new at perl, and I greatly appreciate the help this community is giving me.
 
>- why (&when) perl insists on having spaces inside parentheses

Perl almost never insists on spaces inside parentheses. (Perl almost never insists on anything, that why there's more than one way to so it.) The whitespace improves readability which is why I, and probably Charles as well, used it in the above code. In function calls and test statements for [tt]if[/tt] and [tt]while[/tt] you can put as much (or as little) whitespace ( even
newlines! ) as you like (or don't like). So you can write
Code:
dehash ( 
         %   {     
            $    hit   [  1   ]   
           } 
       );
# I actually surprised myself with howmuch whitespace i could add
#OR
dehash(%{$hit[1]});

>>- what makes a symbolic reference faster and why i should avoid using them

References are faster for the same reason as in C that passing pointers is faster that passing the array. Only the reference to (the address of) the data structure has to be pushed onto the stack; whereas in passing an array or a hash directly, the entire data structure must be copied onto the stack before the function call. (Essentially, a copy of the data structure must be made and passed to the function). For large and/or complicated data structures, this can have a noticeable effect on performance.

Another issue arises when passing more than one data structure to a function. If two arrays get passed to a function, they arrive to the function in the @_ variable as one long list.
So
Code:
myfunc(@ary1, @ary2);
sub myfunc {
  (@myary1, @myary2) = @_;
}
doesn't work like you would expect it to. To accomplish this you would need to do
Code:
myfunc(\@ary1, \@ary2);
sub myfunc {
  ($myaryref1, $myaryref2) = @_;
  # use @$myaryref1 or $$myaryref2[i] here
}

jaa

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top