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

I am converting a hash of arrays to an array of arrays.

I can access the array in the hash as an array. but not its individual elements.

I'm sure that's because I don't understand the syntax.

This code compiles without syntax errors.

$tnum=0; foreach $thread (keys %threads) { print "\n thread for $thread, tnum=$tnum:"; #dbg print "\n\tthe array from hash=@{$threads{$thread}}"; #dbg # THE ABOVE LINE CORRECTLY PRINTS THE ELEMENTS OF THE ARRAY OF THE HAS +H $tsub[$tnum] = $thread; $tsize[$tnum] = @{$threads{$thread}}; print "\n\ttsize[tnum]= @tsize[$tnum]"; #dbg for ($i=0; $i<$tsize[$tnum] ; $i++) { $tlist[$tnum][$i] = ${$threads{$thread[$i]}}; # HERE I'M TRYING TO PRINT THE ELEMENTS ONE AT A TIME print "\n\t{threads{thread[$i]}}=${$threads{$thread[$i]}}"; # BUT THE ABOVE LINE PRINTS ONLY A NULL }
Can anyone show me my mistake? Thanks.

Replies are listed 'Best First'.
Re: syntax of multidimensional arrays and hashes
by jethro (Monsignor) on Jul 18, 2009 at 01:17 UTC

    As anon monk already said, turn on warnings. He is wrong on the cause of your problem though, $tsize[$tnum] is (as you expected) the size of the array in the hash of arrays

    But in the following line you write $thread[$i] which would try to access an element of the array @thread which simply doesn't exist. What you wanted to do was:
    for ($i=0; $i<$tsize[$tnum] ; $i++) { $tlist[$tnum][$i] = $threads{$thread}[$i];

    Note that you can eliminate this loop. The following is equivalent to the two lines above

    push( @{$tlist[$tnum]}, @{$threads{$thread}} );
      Actually, the element of the array Does exist, as I printed out from the hash in the code above the segment I posted. I tried not to post too much code, since the rest worked. Using $tlist$tnum$i = $threads{$thread}$i; as you suggested, I still got a null instead of a number printed. Then I replaced the loop with the push you recommended, and got the syntax error: "Type of arg 1 to push must be array (not array element)at that line number near "]" " Accordingly I then replaced the $tlist$tnum with the array @tlist, and then got the syntax error "syntax error", without further comment.

        Could there be some mistake in the copying of the code? I tested my code and it works (both versions). Here is my complete sample code. Be sure to use the download button underneath before you copy/paste the code so you don't copy word wrapped lines. And remember that for the code with the push you also need to remove the closing '}' of the loop.

        #!/usr/bin/perl use warnings; %threads=('a', [1,2,3], 'b', [2,2,3], 'e', [3,2,3], 'd', [4,2,3], 'c', [5,2,3]); $tnum=0; foreach $thread (keys %threads) { print "\n thread for $thread, tnum=$tnum:"; #dbg print "\n\tthe array from hash=@{$threads{$thread}}"; #dbg # THE ABOVE LINE CORRECTLY PRINTS THE ELEMENTS OF THE ARRAY OF THE HAS $tsub[$tnum] = $thread; $tsize[$tnum] = @{$threads{$thread}}; print "\n\ttsize[tnum]= $tsize[$tnum]"; #dbg # for ($i=0; $i<$tsize[$tnum] ; $i++) # { $tlist[$tnum][$i] = $threads{$thread}[$i]; push( @{$tlist[$tnum]}, @{$threads{$thread}} ); # HERE I'M TRYING TO PRINT THE ELEMENTS ONE AT A TIME print "\n\t\@{threads{thread}}=@{$threads{$thread}}"; # BUT THE ABOVE LINE PRINTS ONLY A NULL }

        which gives me the following output (note that as LanX found out you don't increment tnum, so there is still a bug in this code):

        Name "main::tsub" used only once: possible typo at ./t7.pl line 17. Name "main::tlist" used only once: possible typo at ./t7.pl line 22. thread for e, tnum=0: the array from hash=3 2 3 tsize[tnum]= 3 {threads{thread[0]}}=3 2 3 thread for c, tnum=0: the array from hash=5 2 3 tsize[tnum]= 3 {threads{thread[0]}}=5 2 3 thread for a, tnum=0: the array from hash=1 2 3 tsize[tnum]= 3 {threads{thread[0]}}=1 2 3 thread for b, tnum=0: the array from hash=2 2 3 tsize[tnum]= 3 {threads{thread[0]}}=2 2 3 thread for d, tnum=0: the array from hash=4 2 3 tsize[tnum]= 3 {threads{thread[0]}}=4 2 3
Re: syntax of multidimensional arrays and hashes
by LanX (Saint) on Jul 18, 2009 at 01:22 UTC
    your code/intention is very hard to understand, even when knowing your former question in hash of arrays to array of arrays. Especially $thread[$i] confuses me, where does this array come from?

    You should better stay in that former thread and continue to evolve code on the base of the answers you got, so we can understand what you really want.

    And you should better have a look into the docs for data structures perldsc

    Cheers Rolf

      Rolf: I showed where that came from in the post of a few days ago where I posted the entire program. I have a hash, %threads. The key is a string $thread, and the value is an array of numbers. This is how I printed the hash after it was constructed: foreach $thread (keys %threads) { print "$thread: @{$threads{$thread}}\n";} And that worked properly, exactly as expected. The code I posted here was an attempt to transfer the end arrays from members of the hash to members of an array. I initially tried to transfer each array as a whole. That gave me the problems I described in the previous post. The answers I got then didn't help, so I thought I'd try to do less cleverly, and transfer the elements of the array rather than the whole array. That's where the index $i comes from.
Re: syntax of multidimensional arrays and hashes
by Anonymous Monk on Jul 18, 2009 at 00:43 UTC
      In the program, I print out $tsize$tnum immediately after the assignment, and it prints a number, the correct number. So it is not a reference but a number.
Re: syntax of multidimensional arrays and hashes
by Marshall (Canon) on Jul 18, 2009 at 04:05 UTC
    "I am converting a hash of arrays to an array of arrays.
    I can access the array in the hash as an array. but not its individual elements.
    I'm sure that's because I don't understand the syntax."

    I agree with that!

    foreach $thread (keys %threads) { print "thread=$thread, values are ". @{$threads($thread)}."\n "; }
    Past that, I don't understand the context of what you are trying to accomplish. The rest looks like "mumbo-jumbo" to me. Sorry that I don't understand, but I just don't.
    $tsize[$tnum] = @{$threads{$thread}};
    is nonsense.
      Sorry that I don't understand, but I just don't.
      $tsize[$tnum] = @{$threads{$thread}};
      is nonsense.

      Well syntactically it's correct %threads is a HoA, so @tsize is supposed to hold the sizes of these (now indexedč) arrays.

      I agree that it's hard to imagine why to store the sizes statically...

      Cheers Rolf

      (1) Well should be noted that $tnum is initialized but never incremented... :-)

        The weird part here is that $tsize[$tnum] has pretty much no useful meaning in the code. In a list context, @{$threads{$thread}} has all the values in $threads{$threads}. In a scalar context @{$threads{$thread}} is the number of things in the @{$threads{$thread}} list.

        $tsize[$tnum] = @{$threads{$thread}};
        doesn't appear to have any real meaning or usefulness.

        use @{$threads{$thread}} instead of trying to assign a scalar value to a 'C' style @tsize array.

        Rolf: >should be noted that $tnum is initialized but never incremented< Yes it is - I just cut it off when copying the code to post it this time. It's there in the full code I posted previously.
      $tsize$tnum = @{$threads{$thread}}; # number of items in the thread Ah, the beauty of Perl! It looks like nonsense, but it works <G> $threads{...} is the hash $thread is the key of the hash $threads{$thread} is the value for that key, which is an array Putting the @ in front of the array returns the size of the array. And, that's is what is correctly printed out. It's one of the FEW things I did correctly! <G>
        VOILA! THIS WORKS!

        $tnum=0; foreach $thread (keys %threads) { $tsub[$tnum] = $thread; $tsize[$tnum] = @{$threads{$thread}}; print "\n\ttsize[tnum]= @tsize[$tnum]"; #dbg for ($i=0; $i<$tsize[$tnum] ; $i++) { $tlist[$tnum][$i] = $threads{$thread}[$i]; print "\n\t{threads{thread[$i]}}= $threads{$thread}[$i]"; print "\n\tt +list[$tnum][$i]= $tlist[$tnum][$i]"; #dbg } $tnum++; } }
        I had an extra ${...} around the assignment statement in the inner loop! Thanks to all who made suggestions! Harvey