Beefy Boxes and Bandwidth Generously Provided by pair Networks Frank
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Re: scanning hash

by ysth (Canon)
on Aug 01, 2004 at 09:06 UTC ( #379036=note: print w/ replies, xml ) Need Help??


in reply to scanning hash

keys(%{{reverse %hash}}) <= 1
From the inside out:
  • %hash in list context returns a list of key,value,key,value
  • reverse LIST in list context reverses the list
  • { LIST } returns a ref to an anonymous hash with the given list of keys and values
  • %{ HASHREF } gets the hash given the reference
  • keys %HASH in scalar context returns a count of the keys
Because the anonymous hash is built with keys as the values of the original hash and values as the keys of the original hash, and identical later keys supercede earlier keys, it will have only one key for each unique value from the original hash. So if it ends up with 1 key all the values of the original hash were equal (and if it ends up with 0 keys, the original hash was empty, which may or may not count as having all values equal).


Comment on Re: scanning hash
Select or Download Code
Re^2: scanning hash
by davido (Archbishop) on Aug 01, 2004 at 09:20 UTC

    I love that solution. Here it is in the form of a sub. Pass a reference to the hash into the sub. A return value of true means all values are equal. A value of false means there are some not-equal values.

    use strict; use warnings; my %goodhash = qw/one 1 two 1 three 1 four 1 five 1/; my %badhash = qw/one 1 two 2 three 2 four 2 five 2/; foreach my $testhash ( \%goodhash, \%badhash ) { print SameVals( $testhash ) ? "Good.\n" : "Bad.\n"; } sub SameVals { return keys( %{ { reverse %{ $_[0] } } } ) <= 1; }

    Note that this adds a hashref dereference. That's the  %{ $_[0] } part.


    Dave

Re^2: scanning hash
by tachyon (Chancellor) on Aug 01, 2004 at 10:38 UTC

    That works, is brief, and hip. It is possibly not however the most efficient solution as it fails to utilize an iterative, fail fast approach and requires generating and manipulating un-used anon data stuctures. Given the task we can look at less of the hash if we simply fail fast as soon as we detect a non matching value. Depending on the context this may or may not matter. Still a very cool solution though. Wish I had of thought of it. What the hell, I will next time :-)

    print ident( { foo=>1, bar=>1, baz=>1 } ); sub ident { my $value = (values %{$_[0]})[0]; for (values %{$_[0]} ) { return 0 unless $value eq $_; } return 1; }

    cheers

    tachyon

      You'll have to extend that a bit so it properly deals with undef vs empty string.

      sub ident { my $value = ( values %{ $_[0] } )[0]; for ( values %{ $_[0] } ) { no warnings 'uninitialized'; return 0 unless !( defined $value xor defined $_ ) and ( $valu +e eq $_ ); } return 1; }

      It would be better if I could think of a way to skip the $value eq $_ test when both variables are undefined, and still have the entire expression be true, but I can't see a way to do that without an extra test for definedness on one of the values.


      Update after bageler's reply: this was wrong:

      return 0 unless ( defined $value xor defined $_ ) and ( $value eq $_ ) +;

      The condition will only ever be true when comparing an undef with an empty string, but in no other case, because the left expression is only true if the operands are unequal, ie if only one of them is defined. In that case, the right expression can only also be true if the defined value is an empty string.

      Makeshifts last the longest.

        need to change that slightly so it will return true if all the keys are undef:
        return 0 unless defined $_ ? $_ eq $value : defined $value ? 0 : 1
Re^2: scanning hash
by Aristotle (Chancellor) on Aug 01, 2004 at 14:40 UTC
    This code is incorrect. It will treat undefs and empty strings as the same.

    Makeshifts last the longest.

      Undefs and empty strings are equal. The OP wanted to check if all values are equal.

        Oh dear. Next thing we will argue about whether the equality of two values can be determined by the equality of their string representations. :-)

        Makeshifts last the longest.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://379036]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (4)
As of 2014-04-19 13:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (480 votes), past polls