in reply to Re: Re: Re: Optimizing quickly hash tables by checking multiple conditions
in thread Optimizing quickly hash tables by checking multiple conditions
Well I have made it work using foreach loops but I think most people would find it very onorthodox. First I convert the hast table into a table I can more easy process. And I concatenate all the states into one string for easy comparisation. So at the end I will compare the string to match.
The result is a hash table that looks as follows :my %new_hash; foreach my $line (%refdes_bom) { foreach my $states (sort keys %{$refdes_bom{$line}->{STATES}}) { $new_hash{$refdes_bom{$line}->{CPN}} ->{$refdes_bom{$line}->{REFDES}} ->{SIDE} = $refdes_bom{$line}->{SIDE}; $new_hash{$refdes_bom{$line}->{CPN}} ->{$refdes_bom{$line}->{REFDES}} ->{DESC} = $refdes_bom{$line}->{DESC}; push (@{$new_hash{$refdes_bom{$line}->{CPN}} ->{$refdes_bom{$line}->{REFDES}} ->{STATES}}, $states); $new_hash{$refdes_bom{$line}->{CPN}} ->{$refdes_bom{$line}->{REFDES}} ->{STRING} .= $states; } }
Now I still need to make all the matching conditions work. As you can see in the above sample two of the Q keys match, one does not. And probably here I go into the crazy but easy to read way. So the condition was for all the Q.. where the side is the same and all the states are the same we want to bundle.'SB57002020P' => HASH(0x197d78c) 'Q20' => HASH(0x195a120) 'DESC' => 'S TR 2N7002DW 2N SOT-363' 'SIDE' => 'bottom' 'STATES' => ARRAY(0x195a150) 0 88002 'STRING' => 88002 'Q82' => HASH(0x1985f08) 'DESC' => 'S TR 2N7002DW 2N SOT-363' 'SIDE' => 'bottom' 'STATES' => ARRAY(0x1985f38) 0 88001 1 88003 'STRING' => 8800188003 'Q83' => HASH(0x19afd24) 'DESC' => 'S TR 2N7002DW 2N SOT-363' 'SIDE' => 'bottom' 'STATES' => ARRAY(0x19afd54) 0 88001 1 88003 'STRING' => 8800188003
So first of all I need to use a counter because some keys can come back twice with different values. So with using a counter I am able to create multiple keys. After this I will loop through times through the same hash. Once a match is found I need to make sure that the matching key will not be used again in the future looping. I first tried to delete the key but this does not work as it seem that Perl loads the whole loop into memory and deleting the key would result in bad results. So I added a memory tag and check that memory tag for existance. If so then I can skip it. Eventually I got the result. But I am sure that you REAL PROGRAMMERS will say I am nuts. :-)my $count = 1; my $new_count; my $row; my %bundled_hash; foreach my $CPN (%new_hash) { foreach my $REFDES (sort keys %{$new_hash{$CPN}}) { $new_count = length $count; $row = $count; my $i; for ($i = $new_count; $i <= 4; ++$i) # Start with $i = 1 { $row = '0'.$row; } if (not defined $new_hash{$CPN}->{$REFDES}->{MATCH}) { push (@{$bundled_hash{$row}->{$CPN}->{REFDES}},$REFDES); $bundled_hash{$row}->{$CPN}->{SIDE} = $new_hash{$CPN}->{$REFDES} +->{SIDE}; $bundled_hash{$row}->{$CPN}->{DESC} = $new_hash{$CPN}->{$REFDES} +->{DESC}; $bundled_hash{$row}->{$CPN}->{STATES} = $new_hash{$CPN}->{$REFDE +S}->{STATES}; foreach my $REFDES1 (sort keys %{$new_hash{$CPN}}) { if ($new_hash{$CPN}->{$REFDES}->{STRING} eq $new_hash{$CPN}->{ +$REFDES1}->{STRING} && $new_hash{$CPN}->{$REFDES}->{SIDE} eq $new_has +h{$CPN}->{$REFDES1}->{SIDE} && $REFDES ne $REFDES1) { #$bundled_hash{$row}->{$CPN}->{REFDES} = $REFDES; + push (@{$bundled_hash{$row}->{$CPN}->{REFDES}},$REFDES1); + $new_hash{$CPN}->{$REFDES1}->{MATCH}=1; } } } $count++; } }
Result Hash :
As you see in the result code I have reduced the sections from three to two.00167 => HASH(0x19c39a8) 'SB57002020P' => HASH(0x19c39c0) 'DESC' => 'S TR 2N7002DW 2N SOT-363' 'REFDES' => ARRAY(0x19c39d8) 0 'Q20' 'SIDE' => 'bottom' 'STATES' => ARRAY(0x1980a44) 0 88002 00168 => HASH(0x19c5404) 'SB57002020P' => HASH(0x19c541c) 'DESC' => 'S TR 2N7002DW 2N SOT-363' 'REFDES' => ARRAY(0x19c5434) 0 'Q82' 1 'Q83' 'SIDE' => 'bottom' 'STATES' => ARRAY(0x1989a10) 0 88001 1 88003
In Section
Seekers of Perl Wisdom