Dear fellow perl programmers,
I wanted to access to this array
my #vsrvAttribs = qw(
Code
Description
vsrv_id
vsrv_name
vsrv_vcpu_no
vsrv_vmem_size
vsrv_vdspace_alloc
vsrv_mgmt_ip
vsrv_os
vsrv_virt_platf
vsrv_owner
vsrv_contact
vsrv_state
);
through a variable composed of a variable and a string suffix, which of course led to the error message like this
Can't use string ("#vsrvAttribs") as an ARRAY ref while "strict refs" in use at cmdbuild.pl line 262.`
Therefore I decided to get the reference to the array through a hash
my %attribs = ( vsrv => #vsrvAttribs );
And this is the code where I need to get the content of aforementioned array
foreach my $classTypeKey (keys %classTypes) {
my #attribs = $attribs{$classTypeKey};
print Dumper(\#attribs);
}
It seems I can get the reference to the array #vsrvAttribs, but when I checked the content of the array with Dumper , the array have got only one element
$VAR1 = [
'Code'
];
Do you have any idea where could be the problem?
How do you store the array in a hash and access it later?
You need to store your array by reference like this:
my %attribs = ( vsrv => \#vsrvAttribs );
Note the backslash before the # sigil. This tells perl that you want a reference to the array.
Then when access the array stored in $attribs{vsrv} you need to treat it as a reference instead of as an array. You'll do something like this:
foreach my $classTypeKey (keys %classTypes) {
# make a copy of the array by dereferencing
my #attribs = #{ $attribs{$classTypeKey} };
# OR just use the array reference if profiling shows performance issues:
my $attribs = $attribs{$classTypeKey}
# these will show the same thing if you haven't done anything to #attribs
# in the interim
print Dumper(\#attribs);
print Dumper($attribs);
}
Why did you only get one value and where did the rest of the array go?
Your missing values from #vsrvAttribs weren't lost they were assigned as keys and values to %attribs itself. Try adding the following just after you made your assignment and you'll see it for yourself:
my %attribs = ( vsrv => #vsrvAttribs );
print Dumper(\%attribs);
You'll see output like this:
$VAR1 = {
'vsrv_contact' => 'vsrv_state',
'vsrv_virt_platf' => 'vsrv_owner',
'vsrv' => 'Code',
'vsrv_name' => 'vsrv_vcpu_no',
'vsrv_mgmt_ip' => 'vsrv_os',
'Description' => 'vsrv_id',
'vsrv_vmem_size' => 'vsrv_vdspace_alloc'
};
This is because perl interpreted your assignment by expanding the contents #vsrvAttribs as multiple arguments to the list literal ():
my %attribs = (
# your key => first value from array
vsrv => 'Code',
# subsequent values of the array
Description => 'vsrv_id',
vsrv_name => 'vsrv_vcpu_no',
vsrv_vmem_size => 'vsrv_vdspace_alloc',
vsrv_mgmt_ip => 'vsrv_os',
vsrv_virt_platf => 'vsrv_owner',
vsrv_contact => 'vsrv_state',
);
This is legal in perl and there are reasons where you might want to do this but in your case it wasn't what you wanted.
Incidentally, you would have been warned that perl was doing something that you might not want if you had an even number of elements in your array. Your 13 elements plush the hash key "vsrv" makes 14 which is even. Perl will take any list with an even number of elements and happily make it into a hash. If your array had another element for 15 elements total with the hash key you would get a warning: Odd number of elements in hash assignment at foo.pl line 28.
See "Making References" and "Using References" in perldoc perlreftut for more information.
If you use a bare array in a hash definition like
my %attribs = ( vsrv => #vsrv_attribs )
the array is expanded and used as key/value pairs, so you will get
my %attribs = (
vsrv => 'Code',
Description => 'vsrv_id',
vsrv_name => 'vsrv_vcpu_no',
vsrv_vmem_size => 'vsrv_vdspace_alloc',
...
)
The value of a Perl hash element can only be a scalar value, so if you want an array of values there you have to take a reference, as shown below
It is also a bad idea to use capitals in Perl identifiers for anything except globals, such as package names. Local names are conventional lower-case alphanumeric plus underscore, so $class_type_key instead of $classTypeKey
use strict;
use warnings;
use Data::Dumper;
my #vsrv_attribs = qw(
Code
Description
vsrv_id
vsrv_name
vsrv_vcpu_no
vsrv_vmem_size
vsrv_vdspace_alloc
vsrv_mgmt_ip
vsrv_os
vsrv_virt_platf
vsrv_owner
vsrv_contact
vsrv_state
);
my %attribs = (
vsrc => \#vsrv_attribs,
);
for my $class_type_key (keys %attribs) {
my $attribs = $attribs{$class_type_key};
print Dumper $attribs;
}
output
$VAR1 = [
'Code',
'Description',
'vsrv_id',
'vsrv_name',
'vsrv_vcpu_no',
'vsrv_vmem_size',
'vsrv_vdspace_alloc',
'vsrv_mgmt_ip',
'vsrv_os',
'vsrv_virt_platf',
'vsrv_owner',
'vsrv_contact',
'vsrv_state'
];
Related
I've been banging my head on this awhile and searched many ways. I'm sure this is going to boil down to being really basic.
I have data in an #array that I want to move to a tree in a %hash.
This might be something more appropriate to JSON? But I haven't delved into it before and I don't need to save out/restore this information.
Desire:
Create a dependent tree of USB devices that can nest under each other that can track the end point (deviceC) through a hub (deviceB) and finally the root (deviceA).
Example:
Simplified (I hope ... this isn't from the actual longer script):
I want to convert an array in this format:
my #array = ['deviceA','deviceB','deviceC'];
to multidimensional hashes equal to:
my %hash = ('deviceA' => { 'deviceB' => { 'deviceC' => '' } } )
that would dump like:
$VAR1 = {
'deviceA' => {
'deviceB' => {
'deviceC' => ''
}
}
};
For just looking at a single device this isn't necessary, but I'm building out an IOMMU -> PCI Device -> USB map that contains many devices.
NOTES:
I'm trying to avoid installing CPAN modules so the script is to similar systems (Proxmox VE)
The last device (deviceC above) has no children
value '' is fine
undef would probably work
mixing the types would work but I need to know how to set that
I will never need to modify or manipulate the hash once created
I don't know the right way to recurse the #array to populate the %hash children. * I want the data horizontal for each USB device
I'd switch to an Object/package but each device can have a different set of children (or none) making it infeasible to know Object names
Some USB devices have no children (root hubs) ... similar to %hash = ('deviceA' => '')
Some have 1 child that is the final device ... similar to %hash = ('deviceA' => { 'deviceB' =>'' } )
Some have multiple steps between the root via additional hub(s) ... similar to %hash = ('deviceA' => { 'deviceB' => { 'deviceC' => '' } } ) or more
Starting point :
This is basic and incomplete but will run:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper qw(Dumper);
# data in from parsing usb device path:
my #array = ['deviceA','deviceB','deviceC'];
# needs to be converted to:
my %hash = ('deviceA' => { 'deviceB' => { 'deviceC' => '' } } );
print "\n\%hash:\n" . Dumper \%hash;
Pseudo-code
This section is NOT working code in any form. I'm just trying to make a note of what I'm thinking. I know the format is wrong, I've tried multiple ways to create this and I'd look even dumber showing all of my attempts :)
I'm very new to refs and I'm not going to try and get that right here. The idea below is:
For each item in #array:
Create a way (either a ref or a copy of the current hash) that can be used next iteration to place the next child
Attach item as a child of the previous iteration with an empty value (that can be appended if there is further iteration)
my #array = ['deviceA','deviceB','deviceC'];
my %hash = {};
my %trackref;
for (#array) {
%trackref = %hash; # a copy of the existing that won't change when %hash updates
$hash{last_child} ::append_child:: $_;
}
You're actually pretty close, but it seems that you need to understand references a bit better. perldoc perlref is probably a good starting point to understand references.
A few mistakes in your code, before looking at the solution:
my #array = [ ... ];: [] creates an arrayref, not an array, which means that #array actually stores a single scalar item: a reference to another array. Use () to initialize an array: my #array = ( ... );.
my %hash = {};: similarly, {} creates a hashref, not a hash. Which means that this lines stores a single hashref in %hash, which will cause this warning: Reference found where even-sized list expected at hash.pl line (because a hash contains keys-values and you only provided a key). Use () for a simple (ie, not a hashref) hash. In this case however, you don't need to initialize %hash: my %hash; and my %hash = () do the same thing (that is, create an empty hash).
%trackref = %hash; copies the content of %hash in %trackref. Which means that, contrary to what the name "trackref" implies, %trackref doesn't contain a reference to anything, but a copy of %hash. Use \%hash to create a reference to %hash.
Note that if you already have a hashref, then assigning it to another variables copies the reference. For instance, if you do my $hash1 = {}; my $hash2 = $hash1, then both $hash1 and $hash2 reference the same hash.
So, fixing those issues in your attempt, we get:
my #array = ('deviceA','deviceB','deviceC');
my %hash;
my $trackref = \%hash;
for my $usb (#array) {
$trackref->{$usb} = {};
$trackref = $trackref->{$usb};
}
print Dumper \%hash;
Which outputs:
$VAR1 = {
'deviceA' => {
'deviceB' => {
'deviceC' => {}
}
}
};
The main change that I did was to replace your $hash{last_child} ::append_child:: $_; by $trackref->{$_} = {};. But the idea remains the same: Attach item as a child of the previous iteration with an empty value to reuse your words.
To help you understand the code a bit better, let's see what happens in the loop step by step:
Before the first iteration, %hash is empty and $trackref references %hash.
In the first iteration, we put deviceA => {} in $trackref (or, more pedantically, we associate {} with the key deviceA in $trackref). Since $trackref references %hash, this puts deviceA => {} in %hash. Then, we store in $trackref this new {} that we just created, which means that $trackref now references $hash{deviceA}.
In the second iteration, we put deviceB => {} in $trackref. $trackeref references $hash{deviceA} (which we created in the previous iteration), which means that %hash is now (deviceA => { deviceB => {} }). We then store in $trackref the new {}.
And so on...
You'll note that in the innermost hash, {} is associated to the key deviceC. When iterating of the hash, you can thus know if you are at the end by doing something like if (%$hash) (instead of just if ($hash) if this last {} would have been undef or ''). Let me know if that's an issue: we can add a bit of code to convert this {} into undef (alternatively, you can do it yourself, it will be a good exercise to get used to references)
Minor remark: #array and %hash are poor array and hash names, because the # already indicates an array, and % already indicates a hash. It's possible that you used those names just for this small example for your question, in which case, no problem. However, if you use those names in your actual code, consider changing them for something more explicit... #usb_devices and %usb_devices_tree maybe?
I'm a novice perl programmer trying to identify which elements are in one array of hashes but not in another. I'm trying to search through the "new" array, identifying the id, title, and created elements that don't exist from the "old" array.
I believe I have it working with a set of basic for() loops, but I'd like to do it more efficiently. This only came after having tried to use grep() and failed.
These arrays are built from a database as such:
use DBI;
use strict;
use Data::Dumper;
use Array::Utils qw(:all);
sub db_connect_new();
sub db_disconnect_new($);
sub db_connect_old();
sub db_disconnect_old($);
my $dbh_old = db_connect_old();
my $dbh_new = db_connect_new();
# get complete list of articles on each host first (Joomla! system)
my $sql_old = "select id,title,created from mos_content;";
my $sql_new = "select id,title,created from xugc_content;";
my $sth_old = $dbh_old->prepare($sql_old);
my $sth_new = $dbh_new->prepare($sql_new);
$sth_old->execute();
$sth_new->execute();
my $ref_old;
my $ref_new;
while ($ref_old = $sth_old->fetchrow_hashref()) {
push #rv_old, $ref_old;
}
while ($ref_new = $sth_new->fetchrow_hashref()) {
push #rv_new, $ref_new;
}
my #seen = ();
my #notseen = ();
foreach my $i (#rv_old) {
my $id = $i->{id};
my $title = $i->{title};
my $created = $i->{created};
my $seen = 0;
foreach my $j (#rv_new) {
if ($i->{id} == $j->{id}) {
push #seen, $i;
$seen = 1;
}
}
if ($seen == 0) {
print "$i->{id},$i->{title},$i->{state},$i->{catid},$i->{created}\n";
push #notseen, $i;
}
}
The arrays look like this when using Dumper(#rv_old) to print them:
$VAR1 = {
'title' => 'Legal Notice',
'created' => '2004-10-07 00:17:45',
'id' => 14
};
$VAR2 = {
'created' => '2004-11-15 16:04:06',
'id' => 86096,
'title' => 'IRC'
};
$VAR3 = {
'id' => 16,
'created' => '2004-10-07 16:15:29',
'title' => 'About'
};
I tried to use grep() using array references, but I don't think I understand arrays, hashes, and references well enough to do it properly. My failed grep() attempts are below. I'd appreciate any ideas of how to do this properly.
I believe the problem with this is that I don't know how to reference the id field in the second array of hashes. Most of the examples using grep() that I've seen are to just look through an entire array, like you would with regular grep(1). I need to iterate through one array, checking each of the values from the id field with the id field from another array.
my $rv_old_ref = \#rv_old;
my $rv_new_ref = \#rv_new;
for my $i ( 0 .. $#rv_old) {
my $match = grep { $rv_new_ref->$_ == $rv_old_ref->$_ } #rv_new;
push #notseen, $match if !$match;
}
I also tried variations on the grep() above:
1) if (($p) = grep ($hash_ref->{id}, #rv_old)) {
2) if ($hash_ref->{id} ~~ #rv_old) {
There are a number of libraries that compare arrays. However, your comparison involves complex data structures (the arrays have hashrefs as elements) and this at least complicates use of all modules that I am aware of.
So here is a way to do it by hand. I use the shown array and its copy with one value changed.
use warnings;
use strict;
use feature 'say';
use List::Util qw(none); # in List::MoreUtils with older Perls
use Data::Dump qw(dd pp);
sub hr_eq {
my ($e1, $e2) = #_;
return 0 if scalar keys %$e1 != scalar keys %$e2;
foreach my $k1 (keys %$e1) {
return 0 if !exists($e2->{$k1}) or $e1->{$k1} ne $e2->{$k1};
}
return 1
}
my #a1 = (
{ 'title' => 'Legal Notice', 'created' => '2004-10-07 00:17:45', 'id' => 14 },
{ 'created' => '2004-11-15 16:04:06', 'id' => 86096, 'title' => 'IRC' },
{ 'id' => 16, 'created' => '2004-10-07 16:15:29', 'title' => 'About' }
);
my #a2 = (
{ 'title' => 'Legal Notice', 'created' => '2004-10-07 00:17:45', 'id' => 14 },
{ 'created' => '2004-11-15 16:xxx:06', 'id' => 86096, 'title' => 'IRC' },
{ 'id' => 16, 'created' => '2004-10-07 16:15:29', 'title' => 'About' }
);
my #only_in_two = grep {
my $e2 = $_;
none { hr_eq($e2, $_) } #a1;
} #a2;
dd \#only_in_two;
This correctly identifies the element in #a2 that doesn't exist in #a1 (with xxx in timestamp).
Notes
This finds what elements of one array are not in another, not the full difference between arrays. It is what the question specifically asks for.
The comparison relies on details of your data structure (hashref); there's no escaping that, unless you want to reach for more comprehensive libraries (like Test::More).
This uses string comparison, ne, even for numbers and timestamps. See whether it makes sense for your real data to use more appropriate comparisons for particular elements.
Searching through a whole list for each element of a list is an O(N*M) algorithm. Solutions of such (quadratic) complexity are usable as long as data isn't too big; however, once data gets big enough so that size increases have clear effects they break down rapidly (slow down to the point of being useless). Time it to get a feel for this in your case.
An O(N+M) approach exists here, utilizing hashes, shown in ikegami answer. This is much better algorithmically, once the data is large enough for it to show. However, as your array carries complex data structure (hashrefs) a bit of work is needed to come up with a working program, specially as we don't know data. But if your data is sizable then you surely want to implement this.
Some comments on filtering.
The question correctly observes that for each element of an array, as it's processed in grep, the whole other array need be checked.
This is done in the body of grep using none from List::Util. It returns true if the code in its block evaluates false for all elements of the list; thus, if "none" of the elements satisfy that code. This is the heart of the requirement: an element must not be found in the other array.
Care is needed with the default $_ variable, since it is used by both grep and none.
In grep's block $_ aliases the currently processed element of the list, as grep goes through them one by one; we save it into a named variable ($e2). Then none comes along and in its block "takes possession" of $_, assigning elements of #a1 to it as it processes them. The current element of #a2 is also available since we have copied it into $e2.
The test performed in none is pulled into a a subroutine, which I call hr_eq to emphasize that it is specifically for equality comparison of (elements in) hashrefs.
It is in this sub where the details can be tweaked. Firstly, instead of bluntly using ne for values for each key, you can add custom comparisons for particular keys (numbers must use ==, etc). Then, if your data structures change this is where you'd adjust specifics.
You could use grep.
for my $new_row (#new_rows) {
say "$new_row->{id} not in old"
if !grep { $_->{id} == $new_row->{id} } #old_rows;
}
for my $old_row (#old_rows) {
say "$old_row->{id} not in new"
if !grep { $_->{id} == $old_row->{id} } #new_rows;
}
But that's an O(N*M) solution, while there exists an O(N+M) solution that would be far faster.
my %old_keys; ++$old_keys{ $_->{id} } for #old_rows;
my %new_keys; ++$new_keys{ $_->{id} } for #new_rows;
for my $new_row (#new_rows) {
say "$new_row->{id} not in old"
if !$old_keys{$new_row->{id}};
}
for my $old_row (#old_rows) {
say "$old_row->{id} not in new"
if !$new_keys{$old_row->{id}};
}
If both of your database connections are to the same database, this can be done far more efficiently within the database itself.
Create a temporary table with three fields, id, old_count (DEFAULT 0) and new_count (DEFAULT 0).
INSERT OR UPDATE from the old table into the temporary table, incrementing old_count in the process.
INSERT OR UPDATE from the new table into the temporary table, incrementing new_count in the process.
SELECT the rows of the temporary table which have 0 for old_count or 0 for new_count.
select id,title,created from mos_content
LEFT JOIN xugc_content USING(id)
WHERE xugc_content.id IS NULL;
Gives you the rows that are in mos_content but not in xugc_content.
That's even shorter than the Perl code.
I have this code segment to put together a hash of parameters which I will pass to a function. The hash value containing the IP address is supposed to be an array reference, but the function I'm passing my parameters to thinks it's a scalar reference.
My code is:
my $paramList = "ldap_ip_addresses=['192.168.1.100']|ldap_port=389|ldap_protocol=ldap";
my #paramTuples = split(/\|/, $paramList);
my %nasProps;
foreach my $paramTuple (#paramTuples) {
my($key, $val) = split(/=/, $paramTuple, 2);
# SetProperties can also take hashes or arrays
my $eval_val = eval $val;
if (ref($eval_val) =~ /ARRAY/) {
$val = \$eval_val;
}
$nasProps{$key} = $val;
}
From the debugger, my parameter hash looks like this:
DB<18> x \%nasProps
0 HASH(0x303f8f0)
'ldap_authentication_type' => 'anonymous'
'ldap_ip_addresses' => REF(0x303fa70)
-> ARRAY(0x8284eb8)
0 '192.168.1.100'
'ldap_port' => 389
'ldap_protocol' => 'ldap'
It looks like a reference to an array so I'm not sure where I'm going wrong.
Since $eval_val is already a reference to an array, there is no need to make a reference to the reference. Change:
$val = \$eval_val;
to:
$val = $eval_val;
You are unnecessarily taking the reference to a reference with
$val = \$eval_val;
You have established on the previous line that $eval_val is a reference to an array, so you can use it as it is without taking a reference to it again.
In addition, you should ignore the result of ref $eval_val except to check that it is true — i.e. $eval_val is a reference of some sort.
Your code should look more like this. You need to fall back to the original $val value only if eval returns undef, usually meaning that the string wasn't compilable code.
Note also that you should reserve capital letters for global Perl variables, such as package names. Lexical variable identifiers should contain only lower-case letters, decimal digits and underscores.
use strict;
use warnings;
my $param_list = "ldap_ip_addresses=['192.168.1.100']|ldap_port=389|ldap_protocol=ldap";
my #param_tuples = split /\|/, $param_list;
my %nas_props;
for my $param_tuple (#param_tuples) {
my ($key, $val) = split /=/, $param_tuple, 2;
$nas_props{$key} = eval($val) // $val;
}
use Data::Dump;
dd \%nas_props;
output
{
ldap_ip_addresses => ["192.168.1.100"],
ldap_port => 389,
ldap_protocol => "ldap",
}
Here is a short alternative in functional style:
my %nasProps =
map /\[/ ? eval : $_,
split /[|=]/, $paramList;
However, it only works if you can guarantee that = is not included in any parameter values.
I try to create an array of perl structures. Each struct contains two scalars and a hash.
Later I want to find an item of the array, get the hash and find a scalar inside the hash.
I can find the item inside the array and get the scalars.
But I don't know hot to correctly get the hash and a value inside it.
I tried with/without reference.
Thanks a lot
#hash
%latestInfo = (
8 => '30',
);
#struct
package Myobj;
use Class::Struct;
struct( name => '$', majorVer => '$', latestVer => '%');
$w1 = new Myobj;
$w1->name('test');
$w1->majorVer(5);
$w1->latestVer($latestInfo);
#array with all version information
#versions=($w1, ...);
sub getVersionFromMajor
{
foreach $ver (#versions) {
if ($ver->majorVer eq $_[0]) {
return $ver;
}
}
}
#
#main
#
#ok: get version info from structures/array
local($ver) = getVersionFromMajor(5);
local($n) = $ver->name;
#fail: get hash inside item
my $latest = \$ver->latestVer;
%lat = $ver->latestVer;
#fail: get value inside hash
local($m) = $latest{8};
This bit:
$w1->latestVer($latestInfo);
Should be:
$w1->latestVer(\%latestInfo);
%latestInfo and $latestInfo are two unrelated variables - %latestInfo is your hash, and $latestInfo is an undeclared (and thus undef) scalar. \%latestInfo is a scalar reference to %latestInfo, which is what the latestVer method (created by Class::Struct) wants you to give it.
Perl would have told you about $latestInfo not existing if you'd done use strict and declared all your variables.
Also, this bit:
%lat = $ver->latestVer;
Should be:
%lat = %{ $ver->latestVer };
The background
I got a Perl module which utilizes an array for its input/output parameters, like this:
Execute({inputfile => $req->{modules}.'filename', param => \#xchange});
Inside the module a hash is build and returned via reference
$param[0] = \%values;
This is all fine and good (I think) and print Dumper #xchange[0]; will output my desired content as
$VAR1 = { '33' => 'Title1', '53' => 'Title2', '21' => 'Title3' };
The goal
I would like to loop over the content and print the key/value pairs one by one, for example like this
%testhash = ('33' => 'Test1', '53' => 'Test2', '21' => 'Test3' );
foreach $key (keys %testhash) {
print "LOOP: $key, value=$testhash{$key}\n";
}
This loop does work as intended and dumping my testhash via print Dumper \%testhash; outputs the same as the array element above
$VAR1 = { '33' => 'Test1', '53' => 'Test2', '21' => 'Test3' };
The problem
The trouble now seems to be that although both structures appear to be of the same kind I cant get my head arround, how to properly access the returned hash which is stored inside #xchange[0].
I did try %realhash = #xchange[0]; and %realhash = \#xchange[0];, but then print Dumper \%realhash; will output $VAR1 = { 'HASH(0xa7b29c0)' => undef }; or $VAR1 = { 'REF(0xa7833a0)' => undef }; respectively.
So I either need a way to get the content of #xchange[0] inside a clean new hash or a way to foreach loop over the hash inside the #xchange[0] element.
I guess I am getting screwed by the whole hash reference concept, but I am at a loss here and can't think of another way to google for it.
$xchange[0] is a hash reference. Use the dereference operator %{...} to access it as a hash.
%realhash = %{$xchange[0]};
#xchange[0] is a scalar value, it contains the reference to a hash. When you assign it to a hash
%hash = #xchange[0];
The reference is stringified into something like HASH(0xa7b29c0), and you get the warnings
Scalar value #xchange[0] better written as $xchange[0] at ...
Reference found where even-sized list expected at ...
That is to say, you get these warnings, unless you have been so foolish as to not turn warnings on with use warnings.
The first one means what it says. The second one means that the list you assign to a hash should have an even number of elements: one value for every key. You only passed a "key" (something that Perl took as a key). The value then becomes undef, as noted in your Data::Dumper output:
$VAR1 = { 'HASH(0xa7b29c0)' => undef }
What you need to do is dereference the reference.
my $href = $xchange[0];
my %hash = %$href; # using a transition variable
my %hash2 = %{ $xchange[0] } # using support curly braces
perldsc
use warnings;
use strict;
use Data::Dumper;
$Data::Dumper::Sortkeys=1;
my %testhash = ('33' => 'Test1', '53' => 'Test2', '21' => 'Test3' );
# Add hash as first element of xchange AoH
my #xchange = \%testhash;
# Derefererence 1st element of AoH as a hash
my %realhash = %{ $xchange[0] };
# Dump new hash
print Dumper(\%realhash);
__END__
$VAR1 = {
'21' => 'Test3',
'33' => 'Test1',
'53' => 'Test2'
};