use 5.018001; use warnings; use Benchmark qw(:hireswallclock cmpthese ); use Test::More; my $AoH; my @cmpf = qw( map_map map_direct map_keys grep_map list_join ); my %test = map { $_ => \&$_ } "slice_join", @cmpf; my $n_rec = 1; for (1 .. 5) { say ""; say "=== num of records is: ", $n_rec; $AoH = create_data (1, $n_rec); my $sj = [ sort &slice_join ]; is_deeply ([ sort $test{$_}->() ], $sj, "slice_join === $_") for @cmpf; cmpthese (-3, \%test); $n_rec *= 10; } done_testing; sub list_join { my %H; %H = (%H, %$_) for @$AoH; return keys %H; } # list_join sub slice_join { my %H; @H{keys %$_} = () for @$AoH; return keys %H; } # slice_join sub grep_map { my %seen; return grep { !$seen{$_}++ } map { keys %$_ } @$AoH; } # grep_map sub map_map { my %H = map { $_ => 1 } map { keys %$_ } @$AoH; return keys %H; } # map_map sub map_direct { my %H = (map %$_, @$AoH); return keys %H } # map_direct sub map_keys { my %H; @H{map keys %$_, @$AoH} = (); return keys %H } # map_keys sub create_data { my ($density, $records) = @_; my @AoH; push @AoH, {map { rand 100 <= $density ? ("$_" => $_) : () } "A" .. "ZZ"} for 1 .. $records; return \@AoH; }