Consider this array:
my @array = (hashref1, hashref2, hashref3, hashref1);
How can I remove the duplicate reference hashref1?
Consider this array:
my @array = (hashref1, hashref2, hashref3, hashref1);
How can I remove the duplicate reference hashref1?
If by "duplicate reference" you mean they both refer to the same anonymous hash, you can use List::Util's uniq:
#!/usr/bin/perl
use warnings;
use strict;
use List::Util qw{ uniq };
use Data::Dumper;
my $hashref1 = {a => 10};
my $hashref2 = {b => 11};
my $hashref3 = {c => 12};
my @array = ($hashref1, $hashref2, $hashref3, $hashref1);
print Dumper(uniq(@array));
Output:
$VAR1 = {
'a' => 10
};
$VAR2 = {
'b' => 11
};
$VAR3 = {
'c' => 12
};
The stringified versions of the references will be used for comparison, i.e. something like HASH(0x560ee5fdf220). The same references have the same address.
But, if you mean they refer to different objects with the same contents, you need to find a way how to stringify the hashrefs so that the contents is always the same.
#!/usr/bin/perl
use warnings;
use strict;
use List::Util qw{ uniq };
use Data::Dumper;
my $hashref1 = {a => 10, A => 2};
my $hashref2 = {b => 11, B => 3};
my $hashref3 = {c => 12, C => 4};
my $hashref4 = {a => 10, A => 2};
my @array = ($hashref1, $hashref2, $hashref3, $hashref4);
my @serialized = do {
# Comment out the following line to see how 1 and 4
# can be different sometimes.
local $Data::Dumper::Sortkeys = 1;
map Dumper($_), @array;
};
my $VAR1;
print Dumper(map eval, uniq(@serialized));
perlfaq4 has How can I remove duplicate elements from a list or array?. In the grep method, it doesn't matter that they are hash references because references pointing to the same data will stringify to the same thing (something like HASH(0x12345678):
use v5.10;
use Data::Dumper;
my $hashref_1 = { one => 1 };
my $hashref_2 = { two => 2 };
my $hashref_3 = { tre => 3 };
my @array = ( $hashref_1, $hashref_2, $hashref_3, $hashref_1);
say Dumper( \@array );
{
my %Seen;
@array = grep { ! $Seen{$_}++ } @array;
};
say Dumper( \@array );
The output shows @array before and after the grep. Notice that in the first bit of Dumper output it knows that the last element is the same as the first, so it references that ($VAR1->[0]):
$VAR1 = [
{
'one' => 1
},
{
'two' => 2
},
{
'tre' => 3
},
$VAR1->[0]
];
$VAR1 = [
{
'one' => 1
},
{
'two' => 2
},
{
'tre' => 3
}
];
Now try this when the fourth hash ref has the same key and value as the first hash ref, but is a separate hash:
use v5.10;
use Data::Dumper;
my $hashref_1 = { one => 1 };
my $hashref_2 = { two => 2 };
my $hashref_3 = { tre => 3 };
my $hashref_4 = { one => 1 }; # only looks like $hashref_1
my @array = ( $hashref_1, $hashref_2, $hashref_3, $hashref_4 );
say Dumper( \@array );
{
my %Seen;
@array = grep { ! $Seen{$_}++ } @array;
};
say Dumper( \@array );
Now the array is the same before and after because no reference is repeated. Each reference points to different data:
$VAR1 = [
{
'one' => 1
},
{
'two' => 2
},
{
'tre' => 3
},
{
'one' => 1
}
];
$VAR1 = [
{
'one' => 1
},
{
'two' => 2
},
{
'tre' => 3
},
{
'one' => 1
}
];