in reply to How to test all elements in a list are hashes?

Okay, testing for an empty list is probably the most elegant way to do it. But what about the actual test, is it better to use say: -
print @$x && !grep({ref($_) ne 'HASH'} @$x),"\n";
over
print @$x && @$x == grep({ref($_) eq 'HASH'} @$x),"\n";
?

Replies are listed 'Best First'.
Re^2: How to test all elements in a list are hashes?
by Random_Walk (Prior) on Jan 17, 2005 at 17:07 UTC

    Looks like the double negative way is the fastest except for the empty set. In all other cases the ones comparing the array to the grep'd version may have a lot of comparisons to do before they discover inequality.

    #!/usr/bin/perl -l use strict; use warnings; use Benchmark; my (@a, @b, @c, @d, @e); @a=({}, {}, {}, {}, {}, {}, {}, {}, {}, {}); push @b, @a for (1..10000); push @c, @b, "a"; push @d, "a", @b; @e=(); sub trinary { my $a=shift; print ((@$a == grep {ref $_ eq "HASH"} @$a) ? @$a ? 1 : 0 : 0) } sub double_neg { my $a=shift; print @$a && !grep({ref($_) ne 'HASH'} @$a); } sub equality { my $a=shift; print @$a && @$a == grep({ref($_) eq 'HASH'} @$a); } timethese(9000000, { 'a trinary' => trinary(\@a), 'a double_neg' => double_neg(\@a), 'a equality' => equality(\@a), 'b trinary' => trinary(\@b), 'b double_neg' => double_neg(\@b), 'b equality' => equality(\@b), 'c trinary' => trinary(\@c), 'c double_neg' => double_neg(\@c), 'c equality' => equality(\@c), 'd trinary' => trinary(\@d), 'd double_neg' => double_neg(\@d), 'd equality' => equality(\@d), 'e trinary' => trinary(\@e), 'e double_neg' => double_neg(\@e), 'e equality' => equality(\@e), }); __DATA__ a double_neg: -1 wallclock secs ( 0.47 usr + 0.09 sys = 0.56 CPU) @ +16071428.57/s (n=9000000) a equality: -1 wallclock secs ( 0.62 usr + -0.01 sys = 0.61 CPU) @ +14754098.36/s (n=9000000) a trinary: 4 wallclock secs ( 0.81 usr + 0.05 sys = 0.86 CPU) @ +10465116.28/s (n=9000000) b double_neg: 3 wallclock secs ( 0.72 usr + 0.00 sys = 0.72 CPU) @ +12500000.00/s (n=9000000) b equality: 0 wallclock secs ( 0.75 usr + -0.07 sys = 0.68 CPU) @ +13235294.12/s (n=9000000) b trinary: 6 wallclock secs ( 0.77 usr + 0.00 sys = 0.77 CPU) @ +11688311.69/s (n=9000000) c double_neg: -2 wallclock secs ( 0.52 usr + -0.02 sys = 0.50 CPU) @ +18000000.00/s (n=9000000) c equality: 3 wallclock secs ( 0.61 usr + 0.07 sys = 0.68 CPU) @ +13235294.12/s (n=9000000) c trinary: 0 wallclock secs ( 0.54 usr + 0.00 sys = 0.54 CPU) @ +16666666.67/s (n=9000000) d double_neg: -4 wallclock secs ( 0.29 usr + 0.00 sys = 0.29 CPU) @ +31034482.76/s (n=9000000) (warning: too few iterations for a reliable count) d equality: 0 wallclock secs ( 0.69 usr + 0.00 sys = 0.69 CPU) @ +13043478.26/s (n=9000000) d trinary: 2 wallclock secs ( 0.56 usr + -0.05 sys = 0.51 CPU) @ +17647058.82/s (n=9000000) e double_neg: 7 wallclock secs ( 0.77 usr + 0.06 sys = 0.83 CPU) @ +10843373.49/s (n=9000000) e equality: 1 wallclock secs ( 0.62 usr + 0.00 sys = 0.62 CPU) @ +14516129.03/s (n=9000000) e trinary: 1 wallclock secs ( 0.53 usr + 0.06 sys = 0.59 CPU) @ +15254237.29/s (n=9000000)

    Cheers,
    R.

    Pereant, qui ante nos nostra dixerunt!
      Brilliant - just what I was looking for! If I discover any alternative idioms I shall use Benchmark.pm to test them.