in reply to working with hashes of arrays

First, $a and $b are special variables, and you shouldn't ever name your variables with those names. Never ever.

Second, this line has a couple of problems:

for my $b ( 0 .. $#{$array_of_lists->{$b}} )

You're using $b on the same line where it's declared with my, and you're using $array_of_lists as a hash reference, when you mean to use the %array_of_lists hash. I think what you mean is "$#{ $array_of_lists{$a} }" but again, rename $a and $b. Even at that, your %array_of_lists keys start at 1, so you really want this:

for my $b ( 1 .. scalar @{$array_of_lists{$a}} )

There are other places you're misusing %array_of_lists, but I won't mention them all. This should get you on the right track.

You might also want to look at perlreftut, perlref, and References quick reference.

Replies are listed 'Best First'.
Re^2: working with hashes of arrays
by Anonymous Monk on Dec 02, 2008 at 01:46 UTC
    Ok, cleaned it up alot, and the only error I'm getting now is: "Can't use string ("AdAh") as ARRAY ref while "strict refs" in use. Also, "AdAh" is coming from the first element in array @list3. So, I have it narrowed down to this statement the below statment. Also, can I splice out elements from the arrays on the fly (without having any problems). Thanks in advance. if (substr($my_pocket, 0, 2) eq substr($array_of_lists{$key}[$t], 0, 2)) Code:
    my %array_of_lists = ('0' => [@list3], '1' => [@list4], '2' => [@list8 +99]); #my @array_of_lists = (@list3, @list4, @list899); ##Set my hand my $my_pocket = 'AcAd'; my ($key, $t); for $key ( 0 .. scalar(keys %array_of_lists)) { #The loop will iterate through each element (hand of current h +andlist) of the current row and remove any #hand that contains the cards assigned randomly above. for $t ( 0 .. scalar @{$array_of_lists{$key}} ) { #If the first card of the random hand above equal the firs +t card in the element I am currently on, then remove the element from + this handlist by #splicing it out. Or if the first card of the random hand +above equal the second card of the element (hand) I am currently spli +ce it out. if (substr($my_pocket, 0, 2) eq substr($array_of_lists{$ke +y}[$t], 0, 2)) { $array_of_lists{$key} = splice(@{$array_of_lists{$key} +}, $t, 1); } elsif (substr($my_pocket, 0, 2) eq substr($array_of_lists{ +$key}[$t], 2, 2)) { $array_of_lists{$key} = splice(@{$array_of_lists{$key} +}, $t, 1); } elsif (substr($my_pocket, 2, 2) eq substr($array_of_lists{ +$key}[$t], 0, 2)) { $array_of_lists{$key} = splice(@{$array_of_lists{$key} +}, $t, 1); } elsif (substr($my_pocket, 2, 2) eq substr($array_of_lists{ +$key}[$t], 2, 2)) { $array_of_lists{$key} = splice(@{$array_of_lists{$key} +}, $t, 1); } } }
      The error report you are getting (Can't use string ("AdAh") as ARRAY ref while "strict refs" in use) is happening because one of these assignment statements:
      $array_of_lists{$key} = splice(@{$array_of_lists{$key}}, $t, 1);
      is replacing the original array_ref value of the hash element with a scalar value -- in other words, where $array_of_lists{$key} was originally initialized as a reference to an array, the statement above is assigning a scalar value to that hash element (the last array value returned by splice, which in this case happens to be the only array value returned by splice). Then, in a later iteration of one of those for loops, you are trying to use that hash element as if it were still a reference to an array (but it isn't anymore).

      If you wanted that assignment to preserve the hash value as an array ref, you would have to do it like this:

      @{$hash_of_arrays{$key}} = splice( ... );

      There are other problems with this version of your code, involving the for loops. Instead of this:

      my ($key, $t); for $key ( 0 .. scalar(keys %array_of_lists)) { for $t ( 0 .. scalar @{$array_of_lists{$key}} ) {
      You should be doing something like this:
      for my $key ( sort {$a<=>$b} keys %hash_of_lists ) { for my $t ( 0 .. $#{$hash_of_lists{$key}} ) {
      where the "$#" sigil represents the index number of the last element in the array (i.e. "$#array" or "$#{$array_ref}" or "$#{$hash_of_arefs{$key}}"). Note that your version of the for loops will both do one iteration too many (and the outer loop wouldn't work at all if the hash keys were not integers that increment from 0).

      Note also the use of sort for ordering the hash keys; that usage of $a and $b (globals that are always declared by perl) is the reason why you don't use those variable names for other things.

      The commentary in your code is not at all clear -- I have no idea what you are really trying to accomplish -- so I can't tell whether your use of splice is appropriate. (I don't use splice much, because I usually find simpler and clearer ways of reducing arrays -- IMHO, splice is a relatively complicated tool, tending to make its users more prone to mistakes that may be hard to debug. The suggestion below from GrandFather about using grep is a good one.)

      Another point to learn from GrandFather's reply: post a self-contained piece of code that other monks can actually run, without having to make up input data on their own. It really helps to have a clear idea about what sort of data you are trying to handle.

      Last nit-pick about improving the comments: since the terms you are using for your variable names are vague, your comments should specifically refer to particular variable names when describing what they contain and how they interact in the code. And/or you could try using variable names that are more clearly descriptive of what they are for. A step-wise synopsis of the overall procedure/goal of the script would also be helpful -- POD is good for that -- if you can't describe this clearly, how could you expect to write code for it?