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

This is really a two-part question. Part number one:
%images { => copy_1_frag_1_id, => 12345 => copy_1_frag_2_id, => 67890 => key, => val => some_other_key => some_other_val }
I'm trying to test for the presence of each key in the follwing hash which contains 'copy_[0-9]_frag_[0-9]_id. If found, I want to assign the value to $id

Part two:

Elsewhere in the code I'm building a hash called %status. if $status{$client}{'tapes'}{$id} doesn't exist, then push it in.

Here's what I've got, so far:

#!/opt/openv/perl/bin/perl -w use strict; use NBUX; use Data::Dumper; my %images = bpimagelist(); my %status; my $id; foreach my $key (sort keys %images) { my $client = $images{$key}->{'client'}; my $sched_type = $images{$key}->{'schedule_type'}; my $sched_name = $images{$key}->{'sched_label'}; my $policy = $images{$key}->{'policy'}; my $kb = $images{$key}->{'kbytes'}; if (grep "copy\_[0-9]\_frag\_[0-9]\_id", $images{$key}) { $id = $images{$key}->{$_}; } if ( ! exists ( $status{$client}{'policy'}{$policy} )) { push @{$status{$client}{'policy'}} , $policy ; } if ( ! exists( $status{$client}{'tapes'}{$id} )) { push @{$status{$client}{'tapes'}} , $id ; } } print Dumper(\%status);
Here's a snippet of the results of running the above code:
'dbsrv1' => { 'policy' => [ 'dbsrv1_misc_os', 'dbsrv1_misc_os', 'dbsrv1_misc_os', 'dbsrv1_misc_os', 'dbsrv1_dbps_hot', 'dbsrv1_dbps_hot', 'dbsrv1_dbps_hot', 'dbsrv1_arch', 'dbsrv1_arch', 'dbsrv1_os', 'dbsrv1_os', 'dbsrv1_os' ], 'tapes' => [ undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef ], },

Replies are listed 'Best First'.
Re: Pattern-matching hash keys
by Zaxo (Archbishop) on Sep 20, 2003 at 19:39 UTC

    In the conditional of lines 24-26, and again in 28-30, you're testing for the presence of a hash key, then populating that level as an array. Your Dumper output confirms that the array treatment wins. You don't push onto a hash, you assign. Since you have an array, the hash key never exists and each $policy seen goes into the array, duplicate or not.

    Aside from that, I'm unsure what you're asking.

    After Compline,
    Zaxo

      Thanks for your reply! I'm sorry, I wasn't as clear as I could have been
      if ( ! exists ( $status{$client}{'policy'}{$policy} )) { push @{$status{$client}{'policy'}} , $policy ; }
      I'm building a Hash of Hashes of Arrays. In this example, %status is a hash, whose keys are also hashes named $client. Each key "$client" is a hash of arrays. In the above example, there is one key (array) named "policy". "policy" should contain a list of, well, policies.

      Ultimately, I'm trying to create something like:

      %STATUS { Client1, Policy, [ policy1, policy2, policy3 ] ID [ id1, id2, id3 ] }
Re: Pattern-matching hash keys
by kvale (Monsignor) on Sep 20, 2003 at 19:50 UTC
    For your first question, extracting the matched part is best done with the matching  /regexp/ operator:
    $id = $1 if $key =~ /^(copy_\d_frag_\d_id)$/;
    where I have simplified your regexp.

    For the second question, this is a hash, so you add a key-value pair, rather than push onto an array:

    $status{$client}{'tapes'}{$id} = 1;

    Update: corrected a bug in the code.

    -Mark

Re: Pattern-matching hash keys
by BrowserUk (Patriarch) on Sep 20, 2003 at 21:52 UTC

    You don't indicate how big your %images hash is likely to be, but if it will be more than a few 10s of entries, doing a linear search each time using grep and a regex to test if the elements you are after exists is going to become time consuming.

    If your keys will always have a consistant format (as indicated by your first two) of "copy_n_frag_n_id", then most of that information is redundantly duplicated. The only valuable information are the two numbers. Normally, when tables are index by numbers I would think of an array, or in this case an AoAs, but the test for existance suggests that your data is probably sparse. In this case, using a HoHs, with numeric keys allows you to build a sparse data structure whilst retaining the ability to go straight to the entry of choice avoiding the linear search.

    By way of demonstration.

    #! perl -slw use strict; use Data::Dumper; my %images; $images{$1}{$2} = undef while <DATA> =~ m[copy_(\d+)_frag_(\d+)_id]; print Dumper \%images; for my $copy ( 1 .. 9 ) { for my $frag ( 1 .. 9 ) { $images{$copy}{$frag} = int rand 100000 if exists $images{$copy} and exists $images{$copy}{$frag}; } } print Dumper \%images; __DATA__ copy_1_frag_1_id copy_1_frag_2_id copy_1_frag_3_id copy_1_frag_4_id copy_1_frag_5_id copy_1_frag_6_id copy_1_frag_7_id copy_1_frag_8_id copy_1_frag_9_id copy_2_frag_3_id copy_2_frag_5_id copy_2_frag_7_id copy_2_frag_9_id

    Output


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
    If I understand your problem, I can solve it! Of course, the same can be said for you.