Saved has asked for the wisdom of the Perl Monks concerning the following question:

How would I seach a hash case insensitively? Is there a slick way, or do I need to iterate thru?

Replies are listed 'Best First'.
Re: Search a hash case insensitive
by Eliya (Vicar) on Apr 06, 2011 at 16:34 UTC

    Depending on what exactly you need this for, you could maybe transform all keys to the same case (e.g. lower-case) before you put the entries in the hash — in which case you can then do a direct lookup.

      This code will catch duplicate IDs that are identical.
      #!/usr/bin/perl -w #<SortPW2.pl> /etc/passwd sort by ID my $PASSWD="passwd"; my $fpid = open(PFILE, "<$PASSWD") or die "Password File Not Found: $! +\n"; my %ids; while (my $line = <PFILE>) { @ID = split(/:/, $line); my $id = ${ID[0]}; if ($ids{$id}) { print "'$id' is duplicate\n"; } else { $ids{$id} = 1; } }
      I wish also to catch IDs that differ only in case. (ie. root , Root , ROOT) Thanx.
        This is tangentially discussed in How can I remove duplicate elements from a list or array?, a perlfaq. You can construct your hash, and output whenever you hit a duplicate:

        my %seen; while (my $line = <PFILE>) { @ID = split(/:/, $line); my $id = $ID[0]; if ($seen{lc($id)}++) { print "'$id' is duplicate\n"; } }

        Note you had incorrect syntax for accessing a list element. I would also recommend against using variables with the same character sequence but different cases for names.

        Just lowercase the $id you use for the hash lookup:

        my $id = $ID[0]; my $id_lc = lc $id; if ($ids{$id_lc}) { print "'$id' is duplicate\n"; } else { $ids{$id_lc} = 1; }
Re: Search a hash case insensitive
by JavaFan (Canon) on Apr 06, 2011 at 16:42 UTC
    Consider this:
    my %hash = ( fOO => 1, FoO => 2, FOo => 3, );
    and I want to search case insensitively for foo. What value should be returned?
Re: Search a hash case insensitive
by kennethk (Abbot) on Apr 06, 2011 at 16:34 UTC
    If your keys are all lowercase, you can use the lc function to floor your search term (same for uppercase and uc). If your keys are variable case, you could use a second has as a mapping, but would require no key collisions after flooring case to be robust.
Re: Search a hash case insensitive
by toolic (Bishop) on Apr 06, 2011 at 16:31 UTC
Re: Search a hash case insensitive
by locked_user sundialsvc4 (Abbot) on Apr 06, 2011 at 17:16 UTC

    I suggest that you always create a hash-key that consists of (say) lowercased letters.   Then, if necessary, let each hash-element point to an arrayref.   Within each element in that array is the unadulterated key.

    So, the hash serves its intended purpose:   now, as you iterate through the array that you have found, you know each one has a nearly-matching key value.