School Assignment? Project Due Tomorrow? Chat LIVE With A Programming Expert!

Welcome to Dream.In.Code
Become an Expert!

Join 300,420 Programmers for FREE! Get instant access to thousands of experts, tutorials, code snippets, and more! There are 1,527 people online right now. Registration is fast and FREE... Join Now!




redundant deletion of element from hash

 

redundant deletion of element from hash

Sun751

21 Jun, 2009 - 05:26 PM
Post #1

D.I.C Head
**

Joined: 11 Dec, 2008
Posts: 57



Thanked: 1 times
My Contributions
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 in less code!!!
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});
            }
        }
    }



Any suggestion Welcome!!!

Cheers

User is offlineProfile CardPM
+Quote Post


KevinADC

RE: Redundant Deletion Of Element From Hash

21 Jun, 2009 - 10:01 PM
Post #2

D.I.C Regular
Group Icon

Joined: 23 Jan, 2007
Posts: 401



Thanked: 25 times
Dream Kudos: 50
My Contributions
If you really have all those hashes and you really have to search them for the patterns, then your code seems OK to me. Where your code could possibly be improved is using a single data structure, like a hash of hashes instead of multiple hashes. But you will still have to loop through all the hashes to find the patterns and delete the hash keys.
User is offlineProfile CardPM
+Quote Post

dsherohman

RE: Redundant Deletion Of Element From Hash

22 Jun, 2009 - 04:45 AM
Post #3

D.I.C Head
**

Joined: 29 Mar, 2009
Posts: 184



Thanked: 35 times
My Contributions
QUOTE(Sun751 @ 22 Jun, 2009 - 01:26 AM) *

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 in less code!!!


This can be slimmed down quite a bit by taking advantage of hash references. Since you already appear to be using hashrefs for everything, it just makes things that little bit easier:

CODE

my $target;
if ($R_Cinformix) {
  $target = 'oracle';
} elsif ($R_Coracle) {
  $target = 'informix';
} else {
  die "Neither R_Cinformix nor $R_Coracle set!";
}

for my $hashref ($HR_Cwnt, $HR_Cunx) {
  for my $id (keys %$hashref) {
    delete $$hashref{$id} if $id =~ /\.$target/;
  }
}

$target = uc $target;
for my $hashref ($HR_CScomponent, $HR_CWcomponent) {
  for my $id (keys %$hashref) {
    delete $$hashref{$id} if $id =~ /$target/;
  }
}


If the literal . in the keys of the first two hashes isn't crucial to that regex, you could make the regexes case-insensitive (/$target/i) and combine the two "for my $hashref..." loops into a single loop across all four hashrefs.

A couple side notes based on this and your other recent posts:

- Your use of boolean flags seems a bit excessive. If multiple options are mutually exclusive, it's generally better to use a single variable to store the active value rather than a boolean flag for each possibility. e.g., In this case, a single $active_database would be cleaner and more extensible than separate $R_Cinformix and $R_Coracle unless there is a situation in which it would be valid for $R_Cinformix and $R_Coracle to both be true at the same time. (Given that this code pretty much boils down to "if informix is active, blow away all references to oracle, and vice-versa", I feel pretty safe in assuming that it will never be valid for both to be true.)

- Your regexes tend to be of the form /^.*text.*$/. Putting (non-capturing) .* at the beginning or end of a regex is ultimately meaningless, as /text/ alone will match "text" anywhere in the value being tested. /text/ alone is generally considered to be the stylistically better form, as it contains less visual noise (making the meaning clearer), plus it is significantly faster on some regex implementations, since the regex engine isn't wasting time trying to match the .* portions. (I have a feeling that perl's implementation is probably smart enough to optimize them away, but haven't benchmarked the two variations to verify their relative performance in Perl.)
User is offlineProfile CardPM
+Quote Post

Sun751

RE: Redundant Deletion Of Element From Hash

22 Jun, 2009 - 03:24 PM
Post #4

D.I.C Head
**

Joined: 11 Dec, 2008
Posts: 57



Thanked: 1 times
My Contributions
QUOTE(dsherohman @ 22 Jun, 2009 - 04:45 AM) *

QUOTE(Sun751 @ 22 Jun, 2009 - 01:26 AM) *

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 in less code!!!


This can be slimmed down quite a bit by taking advantage of hash references. Since you already appear to be using hashrefs for everything, it just makes things that little bit easier:

CODE

my $target;
if ($R_Cinformix) {
  $target = 'oracle';
} elsif ($R_Coracle) {
  $target = 'informix';
} else {
  die "Neither R_Cinformix nor $R_Coracle set!";
}

for my $hashref ($HR_Cwnt, $HR_Cunx) {
  for my $id (keys %$hashref) {
    delete $$hashref{$id} if $id =~ /\.$target/;
  }
}

$target = uc $target;
for my $hashref ($HR_CScomponent, $HR_CWcomponent) {
  for my $id (keys %$hashref) {
    delete $$hashref{$id} if $id =~ /$target/;
  }
}


If the literal . in the keys of the first two hashes isn't crucial to that regex, you could make the regexes case-insensitive (/$target/i) and combine the two "for my $hashref..." loops into a single loop across all four hashrefs.

A couple side notes based on this and your other recent posts:

- Your use of boolean flags seems a bit excessive. If multiple options are mutually exclusive, it's generally better to use a single variable to store the active value rather than a boolean flag for each possibility. e.g., In this case, a single $active_database would be cleaner and more extensible than separate $R_Cinformix and $R_Coracle unless there is a situation in which it would be valid for $R_Cinformix and $R_Coracle to both be true at the same time. (Given that this code pretty much boils down to "if informix is active, blow away all references to oracle, and vice-versa", I feel pretty safe in assuming that it will never be valid for both to be true.)

- Your regexes tend to be of the form /^.*text.*$/. Putting (non-capturing) .* at the beginning or end of a regex is ultimately meaningless, as /text/ alone will match "text" anywhere in the value being tested. /text/ alone is generally considered to be the stylistically better form, as it contains less visual noise (making the meaning clearer), plus it is significantly faster on some regex implementations, since the regex engine isn't wasting time trying to match the .* portions. (I have a feeling that perl's implementation is probably smart enough to optimize them away, but haven't benchmarked the two variations to verify their relative performance in Perl.)



Your solution is helpful and side notes is brilliant, thanks for your suggestion!!!
Cheers
User is offlineProfile CardPM
+Quote Post

Fast ReplyReply to this topicStart new topic

Time is now: 11/8/09 12:08AM

Live Help!

Be Social

Dream.In.Code RSS Feed Dream.In.Code LinkedIn Group Follow Us On Twitter Fan Us On Facebook

Tutorials

Programming

Web Development

Reference Sheets

Code Snippets

DIC Chatroom

Bye Bye Ads

Monthly Drawing

Thumb Drive

Top Contributors

Top 10 Kudos This Month