Reputation: 5992
How to make a hash
that has been pushed into an array
independent of the "source" hash
?
my %country;
my Hash @array;
%country{ 'country' } = 'France';
@array.push(%country);
%country{ 'country' } = 'Germany';
@array.push(%country);
.say for @array;
The output is:
{country => Germany}
{country => Germany}
And of course it's not what I want.
Upvotes: 3
Views: 699
Reputation: 4558
If you just want a simple key value pair (not a multi part hash) consider Pairs?
my Pair @array;
@array.push( (:country<Germany>) );
@array.push( (country => "France") );
say @array;
say .kv for @array
Upvotes: 1
Reputation: 6723
Just about every programming language has this issue. You're pushing the same hash onto the array more than once. When you change the hash, you change both references that are inside the array.
If you push different hashes onto the array, you'll see the result you expect:
my %a = ( country => 'China' );
my %b = ( country => 'USA' );
my Hash @array;
@array.push(%a);
@array.push(%b);
say @array.perl;
You can even copy the hash when you push it onto the array, instead of declaring two hashes. That will also solve this problem:
my %country;
my @array;
%country<country> = 'México';
@array.push(%country.list.hash);
%country<country> = 'Canada';
@array.push(%country.list.hash);
say @array.perl;
By the way, there are a lot of ways to copy a hash. The key is to get the key/values, then turn it back into a hash. Which hash constructor, and which flattening method you use are up to you. (.kv
, .list
, .pairs
, .flat
are all Hash
methods that will get the elements sequentially, in one way or another. The way Håkon showed is more implicit, getting elements then creating another hash by syntax alone.)
Upvotes: 3
Reputation: 40718
When you push the hash %country
on to the array you are pushing the reference to %country
. In this way, each array element will reference the same original hash %country
. And when you change a value of the hash all array elements will reflect this change (since they all reference the same hash). If you want to create a new hash each time you push it, you can try push an anonymous hash instead. For example:
%country{ 'country' } = 'France';
@array.push({%country});
%country{ 'country' } = 'Germany';
@array.push({%country});
In this way, a reference to a copy of %country
is pushed each time (instead of a reference to %country
).
Output:
{country => France}
{country => Germany}
Upvotes: 3