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

I am trying to increment $hash{$k}[1] += 1 but it's not working! I looked at question #174449, tried $hash{$k}[1]++, but I am still getting 1 as a value. What am I missing? Here is the code:
my %hash=(); %hash=( ##keys between "" because of dots "M01.001" =>["M01.001"]' "M01.001.111" =>["M01.001.111"]' "M01.001.111.111" =>["M01.001.111.111"]' "M01.002" =>["M01.002"]' "M01.002.003" =>["M01.002.003"]' ) for my $k(sort keys %hash){ my $temp = reverse($k); $temp =~ s/^\d{3}\.?//; my $t= reverse ($temp); if (exists $hash{$t}){ $hash{$k}[1] += 1; } }
Thanks.

Edit: Fixed array brackets in text para. davorg

Replies are listed 'Best First'.
Re: Incrementing a hash of array value
by beable (Friar) on Jul 23, 2004 at 10:58 UTC
    It's not apparent what you are trying to do. Here's your code cleaned up with the syntax errors removed:
    #!/usr/bin/perl use strict; use warnings; use Data::Dumper; my %hash=(); %hash=( ##keys between "" because of dots "M01.001" =>["M01.001"], "M01.001.111" =>["M01.001.111"], "M01.001.111.111" =>["M01.001.111.111"], "M01.002" =>["M01.002"], "M01.002.003" =>["M01.002.003"], ); print Dumper(%hash), "\n"; for my $k(sort keys %hash){ my $temp = reverse($k); $temp =~ s/^\d{3}\.?//; my $t= reverse ($temp); if (exists $hash{$t}){ $hash{$k}[1] += 1; } } print Dumper(%hash); __END__

    As for the $hash{$k}[1] += 1; "not working", it is working. It might not be doing what you wanted, but it's doing what somebody would expect, which is to create a second element in the array $hash{$k}, and then add 1 to it, to produce the result 1. If you meant to add 1 to the string "M01.001", what exactly do you think that means? You can't add the integer 1 to a string. It doesn't make sense.

      Sorry for the dubious code. It's actually a long program. So I just typed the above code from memory hoping it would compile. My apologies! Here is what i am trying to achieve. I have a number of strings which I would like to print in a minimal hierarchical format. Instead of Listing all expanded variations on M01 (ie:
      M01.001 M01.001.111 M01.001.111.111 M01.001.111.111.113 ... ... ... etc
      I would only like to print "M01.001 +". Then the user can click on the plus sign to expand and view the next level of the tree structure, the children that is. Orphaned nodes would still show but parents would be assigned a plus sign for expansion. The only way I can do this is by counting all occurrences of a certain string in a data reduction technique. I am using a hash of arrays to do this. The first value of the HoA is a string (ie $hash{$k}[0]) in the example; the second element is the incremented number which I autovivify (ie $hash{$k}1). I hope this makes sense. Is there a better technique to do this? Thanks.
Re: Incrementing a hash of array value
by davorg (Chancellor) on Jul 23, 2004 at 10:55 UTC

    Your code doesn't compile as it stands. Please paste code into your posts, don't try to retype it as you _will_ make mistakes.

    There are a number of errors here, but I don't know how to fix them as I don't understand what you are trying to do. Your code that increments the values never gets called. Let's trace thru the first iteration of the loop to see why...

    The first value that $k gets is 'M01.001'. That is then reversed and put into $temp, so $temp contains '100.10M'. Then your substitution removed the first few characters so $temp contains '10M'. You reverse that and store it in $t, so $t contains 'M01'. You then look for $hash{$t}. But %hash doesn't have a key with the value 'M01', so your "if" condition fails and the increment statement is never executed.

    Does that help?

    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

Re: Incrementing a hash of array value
by EdwardG (Vicar) on Jul 23, 2004 at 10:53 UTC

    Perl arrays start at element 0, not 1 like you seem to be assuming.

     

      I thought that at first. But then I realised that they might be deliberately autovivifying the second element of the array.

      --
      <http://www.dave.org.uk>

      "The first rule of Perl club is you do not talk about Perl club."
      -- Chip Salzenberg

        But that is the root of the OP's problem. They apparently want to increment those 'M01...' strings, relying on the magic of ++.

         

Re: Incrementing a hash of array value
by wfsp (Abbot) on Jul 24, 2004 at 08:06 UTC
    Does this demonstrate what you're after?
    #!/bin/perl5 use strict; use warnings; my %hash=(); %hash=( "M01.001" => 0, "M01.001.111" => 0, "M01.001.111.111" => 0, "M01.002" => 0, "M01.002.003" => 0 ); my %HoA; for my $k ( keys %hash ){ $k =~ /(M\d{2}\.\d{3})/; my $parent = $1; push @{$HoA{$parent}}, $k } foreach my $parent ( sort keys %HoA ) { print "$parent\n"; foreach my $i ( 0 .. $#{$HoA{$parent}} ) { my $child = $HoA{$parent}[$i]; next if $parent eq $child; print "\t$child\n"; } print "\n"; }
    Produces...
    M01.001 M01.001.111 M01.001.111.111 M01.002 M01.002.003
    How complex is the hierarchy? Would any 'children' have 'children' too?

    The second loop came from perldsc. I think what you need is in there somewhere.

      Thanks for looking into this. This would work for the sample data above but breaks when new nodes are added such as (C01, C01.111, D01...) The children have also their own children and the children have siblings. I am after a way to hide the complexity of viewing all nodes. A perfect example of what I am after is available at: http://www.nlm.nih.gov/mesh/2004/MeSHtree.A.html. It's done through CGI.
        change:
        $k =~ /(M\d{2}\.\d{3})/;
        to:
        $k =~ /(\w\d{2}\.\d{3})/;

        If I still haven't understood you properly I would need to see a more complete example of the real data you are using.