caseless compare on hash keys 
Author Message
 caseless compare on hash keys

  I have inherited a program that stores urls as keys in a hash.

  At the moment the program finds out if the url exists using,
  if exists($myHash{$myString}) {...}

  Which is fine, except I want to do this without regard to case.

  One idea:
  my $tmp = uc $myString;
  if grep( /$tmp/,  map(uc, keys(%myHash))) {...}

  This works but the perl doco says
  "map EXPR,LIST
  ...can cause bizarre results if the LIST is not a named array".

  So is this going to fail or cause bizarre results?
  Is there a quicker/better way of doing things?

  John

Sent via Deja.com http://www.*-*-*.com/
Before you buy.



Mon, 10 Feb 2003 03:00:00 GMT  
 caseless compare on hash keys

Quote:

>  I have inherited a program that stores urls as keys in a hash.

>  At the moment the program finds out if the url exists using,
>  if exists($myHash{$myString}) {...}

>  Which is fine, except I want to do this without regard to case.

>  One idea:
>  my $tmp = uc $myString;
>  if grep( /$tmp/,  map(uc, keys(%myHash))) {...}

  my %myUcHash = map { uc $_, $_ } keys %myHash; # Do this once
  ...                                   # Update %myUcHash if %myHash changes
  if (exists $myUcHash{$myString}) { print $myHash{$myUcHash{$myString}} }

Quote:
>  This works but the perl doco says
>  "map EXPR,LIST
>  ...can cause bizarre results if the LIST is not a named array".

Reread the warning.  It says bizarre results can happen if you explicitly
modify $_ during a map().  You're not doing that.
        -Joe

--
See http://www.inwap.com/ for PDP-10 and "ReBoot" pages.



Mon, 10 Feb 2003 03:00:00 GMT  
 caseless compare on hash keys

Quote:

>  my $tmp = uc $myString;
>  if grep( /$tmp/,  map(uc, keys(%myHash))) {...}

>  This works but the perl doco says
>  "map EXPR,LIST
>  ...can cause bizarre results if the LIST is not a named array".

You're missing the context:

#    Note that, because $_ is a reference into the list
#    value, it can be used to modify the elements of the
#    array. While this is useful and supported, it can cause
#    bizarre results if the LIST is not a named array.

It's talking about modifying $_ in the map(), and that's not
what you're doing, so you should be okay.

But note that you're checking to see whether $tmp is *contained*
within the key, not whether they're equal.  Moreover, you're
ignoring the possibility that $tmp could contain regex
metacharacters.  This would be better, though still suboptimal:

    if (grep { $tmp eq uc } keys %myHash) { }

But much better would be to uppercase the strings when you put
them into the hash in the first place (perhaps using the correct
capitalization as the value so that you don't lose it) and then
use

    if (exists $myHash{$myString}) { }

You can drop the "exists " if the hash values are all true.

If the strings are URLs, though, the case-insensitive comparison
seems a bit odd, unless none of them have anything after the
domain name.  The path part of a URL is case-sensitive.

--

Washington, DC



Mon, 10 Feb 2003 03:00:00 GMT  
 caseless compare on hash keys

Quote:

>  I have inherited a program that stores urls as keys in a hash.
>  Which is fine, except I want to do this without regard to case.

Then make the keys all lowercase.  Keep the original URLs as part of
the values, so that you can retrieve them in the original case.

Quote:
>  my $tmp = uc $myString;
>  if grep( /$tmp/,  map(uc, keys(%myHash))) {...}

Works, but horribly slow.  The idea of a hash is that you select the
keys so that you _don't_ need to this.

Quote:
>  This works but the perl doco says
>  "map EXPR,LIST
>  ...can cause bizarre results if the LIST is not a named array".

Read the whole paragraph: "Note that, because $_ is a reference into
the list value, it can be used to modify the elements of the array.
While this is useful and supported, it can cause bizarre results if
the LIST is not a named array. ..."

You're not modifying $_ in the map, so there's no weirdness.

--
Ilmari Karonen - http://www.sci.fi/~iltzu/
Please ignore Godzilla  | "By promoting postconditions to
and its pseudonyms -    |  preconditions, algorithms become
do not feed the troll.  |  remarkably simple."  -- Abigail



Mon, 10 Feb 2003 03:00:00 GMT  
 caseless compare on hash keys

Quote:

>   I have inherited a program that stores urls as keys in a hash.

>   At the moment the program finds out if the url exists using,
>   if exists($myHash{$myString}) {...}

>   Which is fine, except I want to do this without regard to case.

Trick is to uc the URLs when you add them, then uc them when you test,
so...

$myHash{uc $newUrl} = $newValue;

then later

  if exists($myHash{uc $myString}) {...}

- Richard Huxton



Mon, 10 Feb 2003 03:00:00 GMT  
 caseless compare on hash keys


:   I have inherited a program that stores urls as keys in a hash.
:
:   At the moment the program finds out if the url exists using,
:   if exists($myHash{$myString}) {...}
:
:   Which is fine, except I want to do this without regard to case.

An easy solution is to choose a canonical case.  For example:


        $myHash{lc $url} = 1;
    }

    # time passes...

    $url = get_next_url();
    if ($myHash{lc $url}) {
        ...;
    }

:   One idea:
:   my $tmp = uc $myString;
:   if grep( /$tmp/,  map(uc, keys(%myHash))) {...}
:
:   This works but the perl doco says
:   "map EXPR,LIST
:   ...can cause bizarre results if the LIST is not a named array".

Don't worry about that unless you're modifying the value of $_ (which
is aliased to the current scalar in LIST) inside the map EXPR.

Greg
--
A great many people think they are thinking when they are merely rearranging
their prejudices.
    -- William James



Mon, 10 Feb 2003 03:00:00 GMT  
 caseless compare on hash keys

Quote:

>   I have inherited a program that stores urls as keys in a hash.

>   At the moment the program finds out if the url exists using,
>   if exists($myHash{$myString}) {...}

>   Which is fine, except I want to do this without regard to case.

>   One idea:
>   my $tmp = uc $myString;
>   if grep( /$tmp/,  map(uc, keys(%myHash))) {...}

>   This works but the perl doco says
>   "map EXPR,LIST
>   ...can cause bizarre results if the LIST is not a named array".

Here's the full quotation:

] Note that, because C<$_> is a reference into the list value, it can
] be used to modify the elements of the array.  While this is useful and
] supported, it can cause bizarre results if the LIST is not a named
] array

You're not assigning back into the array, so this is OK (and cannot
"cause bizarre results").

--

Compugen Ltd.          |Tel: +972-2-6795059 (Jerusalem) \ We recycle all our Hz
72 Pinhas Rosen St.    |Tel: +972-3-7658514 (Main office)`---------------------
Tel-Aviv 69512, ISRAEL |Fax: +972-3-7658555    http://3w.compugen.co.il/~ariels



Mon, 10 Feb 2003 03:00:00 GMT  
 caseless compare on hash keys

Quote:

>   I have inherited a program that stores urls as keys in a hash.
>   Which is fine, except I want to do this without regard to case.
>   Is there a quicker/better way of doing things?

Get Tie::CPHash from CPAN.

--
John Porter



Mon, 10 Feb 2003 03:00:00 GMT  
 caseless compare on hash keys

Quote:

>    if (exists $myHash{$myString}) { }

>You can drop the "exists " if the hash values are all true.

Like time I checked, using 'exists' when appropriate performs
better. Just thought I'd point that out. I don't always use it when
I should, either...

Cheers,
Douglas Wilson



Tue, 11 Feb 2003 03:00:00 GMT  
 
 [ 9 post ] 

 Relevant Pages 

1. Delphi vs. Powerbuilder??? Hlp Quick Please

2. Source to play sound: FM, WAV, MOD... in Pascal

3. comparing a hash (key only)

4. split composite hash key into sub key fields.

5. hash keys order returned by keys() reproducible ?

6. printing ASCII

7. Sorting by calculated fields

8. Nervous cursor using BP7.0 with Windows95 ?

9. VGA Bios Font...

10. bushpig@mweb.co.za

11. Strange TDBLookupComboBox behavior

12. exists() on sub-hash creates a key in super-hash

 

 
Powered by phpBB® Forum Software