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

So the code
if($_ =~ /^Product\sname:\s(\w.*)/) { $product[$prodCount] =$1; #print "$1<br>\n"; } if($_ =~ /^Option\sName:\s(\w.*)/) { $product[$prodCount][$optionPos] = $1; for my $x (0..$#product) { for my $y (0..$#{$product[$x]}) { print "$product[$x][$y]<br>\n";# $products = join(" " , $products,$product[$x][$y]); } }

The above code is for an order system Im making using multi-dimensional arrays
$product[$x] is the Product Name $product[$x][$y] is the products option list(color, size etc)


The above code uses strict and warnings, so assume that all variables are defined already.

When I run the above code I get the error
Can't use string ("Promo - Product ID 1 ") as an ARRAY ref while "strict refs" in use at modules/productParser + line 77.


Line 77 is $product[$prodCount][$optionPos] = $1;
Any suggestions?

Replies are listed 'Best First'.
Re: Multi-dimensional Array Issue
by ikegami (Patriarch) on Jul 15, 2005 at 19:04 UTC

    $product[$x][$y] is short for $product[$x]->[$y]. In other words, $product[$x][$y] means $product[$x] needs to contain an array ref. However, you claim that $product[$x] contains the product name. $product[$x] cannot contain both an array ref and a product name, so you have a problem with the design of your data structure.

    Perhaps you want something like:

    $product[$x]{name} is the name of product $x. $product[$x]{opts}[$i] is the option $i of product $x. @product is the list of products. map { $_->{name} } @product is the list of product names. @{$product[$x]{opts}} is the list of options of product $x.

    or maybe you'd like to use a hash of products instead of an array of products:

    $product{$name}[$i] is the option $i of product $name. keys %product is the list of product names. @{$product{$name}} is the list of options of product $name.

    (Product names must be unique when using a hash of products.)

      If I go with your suggestion on redoing my code, how would I loop through each option?

        If using an array of products:

        my @products; ... if (/^Product\sname:\s(\w.*)/) { push(@products, { name => $1, opts => [] }); } if (/^Option\sName:\s(\w.*)/) { push(@{$products[-1]{opts}}, $1); } ... foreach my $product (@products) { my $name = $product->{name}; my $opts = $product->{opts}; print($name, ': ', join(' ', @$opts), "\n"); }

        If using a hash of products:

        my %products; ... if (/^Product\sname:\s(\w.*)/) { $name = $1; $products{$name} = []; } if (/^Option\sName:\s(\w.*)/) { push(@{$products{$name}}, $1); } ... foreach my $name (keys %products) { my $opts = $products{$name}; print($name, ': ', join(' ', @$opts), "\n"); }

        Update: Pluralized the array/hash name (@products/%products) to avoid confusion with $product.

        Update: Added initialization code.