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

Below I have got bunch of code which checks either R_Cinformix or R_Coracle is defined, then run the respective deletion of element on same hash. I am just wondering if there is any more smart way to do this task using less code!!!
if ($R_Cinformix) { foreach $id (keys %$HR_Cwnt) { if ($id =~ /.*?\.oracle.*?$/) { delete($$HR_Cwnt{$id}); } } foreach $id (keys %$HR_Cunx) { if ($id =~ /.*?\.oracle.*?$/) { delete($$HR_Cunx{$id}); } } foreach $id (keys %$HR_CScomponent) { if ($id =~ /.*?ORACLE.*?$/) { delete($$HR_CScomponent{$id}); } } foreach $id (keys %$HR_CWcomponent) { if ($id =~ /.*?ORACLE.*?$/) { delete($$HR_CWcomponent{$id}); } } } elsif ($R_Coracle) { foreach $id (keys %$HR_Cwnt) { if ($id =~ /.*?\.informix.*?$/) { delete($$HR_Cwnt{$id}); } } foreach $id (keys %$HR_Cunx) { if ($id =~ /.*?\.informix.*?$/) { delete($$HR_Cunx{$id}); } } foreach $id (keys %$HR_CScomponent) { if ($id =~ /.*?INFORMIX.*?$/) { delete($$HR_CScomponent{$id}); } } foreach $id (keys %$HR_CWcomponent) { if ($id =~ /.*?INFORMIX.*?$/) { delete($$HR_CWcomponent{$id}); } } }

Replies are listed 'Best First'.
Re: redudent hash
by cdarke (Prior) on Jun 22, 2009 at 13:05 UTC
    Your RE '.*?' is a little suspect. What is intended?

    You can use a grep to replace each foreach loop, for example:
    my @keys = grep /.*?\.oracle.*?$/, keys %$HR_Cwnt; delete @$HR_Cwnt{@keys};
    You don't actually need the @keys array, but it makes the code easier to read.
    Update: corrections to wording
      Yeah, the two occurrances of .*? in that regex don't seem to do anything useful. The only thing I can see is that you want to see (for example) whether the string .oracle appears in $id. If that's the case, a simple grep /\.oracle/, $keys %$HR_Cwnt; would be faster.
Re: redudent hash
by Transient (Hermit) on Jun 22, 2009 at 13:00 UTC
    Something to the tune of (CODE UNTESTED):
    my $name = ""; if ($R_Cinformix) { $name = "oracle" } elsif { $R_Coracle ) { $name = "informix" } foreach ( $HR_Cwnt, $HR_Cunx ) { foreach $id ( keys %$_ ) { if ( $id =~ /.*?\.$name.*?$/ ) { delete( $_->{$id} ); } } } $name = uc($name); foreach ( $HR_CScomponent, $HR_CWcomponent ) { foreach $id ( keys %$_ ) { if ( $id =~ /.*?$name.*?$/ ) { delete( $_->{$id} ); } } }
    Update: wow, programming in too many languages. fixed variable "sets"
Re: redudent hash
by citromatik (Curate) on Jun 22, 2009 at 12:56 UTC

    If you are using Perl 5.10 you can use the given ... when construction. See perlsyn

    Update: Sorry, read too fast. Let's try again:

    All the

    foreach $id (keys %$HR_Cwnt) { if ($id =~ /.*?\.oracle.*?$/) { delete($$HR_Cwnt{$id}); } }

    Can be simplified using Tie::Hash::Regex to something like:

    delete $HR_Cwnt->{/.*?\.oracle.*?$/}

    citromatik