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

Hi All,
I was wondering if it is possible to set all values in a multidimensional
array using the x operator? I tried various things but so far the
only way I could find of going about it is something like:

#!/usr/bin/perl -w use strict; my @array = ( [1,1,1],[2,2,2],[3,3,3] ); for my $i ( 0..2 ) { @{$array[$i]} = (0) x 3; } for my $i ( 0..2 ) { for my $j ( 0..2 ) { print "-".$array[$i][$j]; } print "\n"; }

Any ideas on how I can acess it as a 1-D array, or on why I shouldn't?

thanks,
me

--- Try Not To Breathe

Replies are listed 'Best First'.
Re: setting multidimensional array values
by Masem (Monsignor) on May 24, 2001 at 16:57 UTC
    the 'x' operator is only going to work to give you strings. However, here's a time where I've found map to be very useful:
    @{$array[$i]} = map {0} (1..3);

    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
      For those who, like me, were puzzled about the idea of using 'x' in a list context, check out the 'perlop' manpage:

      Binary "x" is the repetition operator. In scalar context, it returns a string consisting of the left operand repeated the number of times specified by the right operand. In list context, if the left operand is a list in parentheses, it repeats the list.

      @ones = (1) x 80; # a list of 80 1's @ones = (5) x @ones; # set all elements to 5

      --- -DA
Re: setting multidimensional array values
by tachyon (Chancellor) on May 24, 2001 at 17:34 UTC

    This does what you want in a one liner. The loop is a little easier to understand if you are unfamiliar with map but they are essentially identical.

    I have also shown you how to make your data access a lot less rigid. This code does not care about the structure of your 2D array which has been made irregular.

    Not sure what you mean by access a 2D array as 1D. Do you want to flatten it into a list? I have coded that for you. Otherwise it is a 2D structure.

    tachyon

    #!/usr/bin/perl -w use strict; # here we have an irregular sized 2D array my @array = ( [1],[2,2],[3,3,3],[4,4,4,4] ); my $all ='42'; # this sets all elements to $all for (@array) { @$_ = ($all) x @$_; } # this also sets all elements to $all # map is just the loop above in short form map{ @$_ = ($all) x @$_ }@array; # this prints the entire structure for (@array) { for (@$_) { print "-",$_; } print"\n"; }

    Explanation. $_ is magical. When we loop over @array each element is aliased to $_ in turn if we modify $_ we modify the actual element @$_ derefs our array elements in list context and allows us to modify them @$_ in scalar context gives the number of elements thus the polymorphic behaviour in this example

    If you want to flatten this 2D array into a 1D array this code does that

    map{ push @list, @$_ }@array; print "@list";
andye Re: setting multidimensional array values
by andye (Curate) on May 24, 2001 at 17:23 UTC
    sub ar_init { (defined $_[1]) ? [ map { ar_init(@_) } (1..shift()) ] : shift() ; } my $r_array = ar_init(3,3,'-');
    ar_init() returns an arrayref, as parameters it takes the dimensions followed by the initial value. So e.g. if you want an array with three dimensions of ten elements, each containing 'foo', you'd use ar_init(10,10,10,'foo').

    But I'll be the first to admit that it might be clearer for future maintainers if you just use for loops!

    Andy.
    update: tiny simplification

Re: setting multidimensional array values
by tachyon (Chancellor) on May 24, 2001 at 17:58 UTC

    small addendum to previous post

    on the subject of maintainability this is really bad!
    but is does print out entire 2D array in one line :-)

    my @array = ( [1],[2,2],[3,3,3],[4,4,4,4] ); map{map{print "-",$_}@$_;print"\n"}@array;

    This code would almost pass for a JAPH now! In fact here is a challenge. Here is some code based on this thread. What does this do, no running it now, that would be cheating ;-)

    my@a=([],[],[],[],[],[],[],[],[],[]); my$a=-1;map{@$_=(++$a)x$a}@a; map{map{print "-",$_}@$_;print"\n"}@a;

    tachyon