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

I created an array of arrays with the following script:
for (@data) { push(@{$arrays}, [split(/ /,$data[$a])]); $a++; }
I now am attempting to create a foreach loop that will allow me to pull out some of those values, foreach @array to put into a hash. I have tried
foreach (@arrays) and foreach (@arrays[0])
but have had no success. Any suggestions?

Lhamo_rin

Replies are listed 'Best First'.
Re: foreach loop with array of arrays
by dragonchild (Archbishop) on Jun 26, 2003 at 17:59 UTC
    First - use strict. That would have caught the obvious error that @arrays and @{$arrays} are not the same thing.

    The second thing is that you're looping over the outer array. But, you're building an ArrayOfArrays. So, you'll need an inner for-loop and an outer for-loop. Here's one way to rewrite your script:

    use strict; # I'm assuming I'm getting @data from some file. use IO::File; my $fh = IO::File->new('Some_filename') || die "Cannot open 'Some_filename' for reading\n"; my @data = <$fh>; $fh->close; # At this point, I have the entire file in @data. my @array; foreach my $line (@data) { push @array, [ split / /, $line ]; } # There are a number of ways I could've written the above statement. # Two others could be: # # my @array; # push @array, [ split / /, $_ ] for @data; # or # my @array = map { split / /, $_ } @data; # # It's completely up to you what you're most comfortable with. # At this point, we're ready to loop through the file. I'm # going to assume you want to print the second and fourth # elements of each line out. (That corresponds to array \ # indices 1 and 3.) foreach my $line_from_file (@array) { foreach my $value (@{$line_from_file}) { # NOTE: Since I'm using array references, I have to # dereference the value using the -> (arrow) operator. print "2nd: $value->[1] ... 4th: $value->[3]\n"; } }
    I hope that helps.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

      That line with map didn't work for me. Try this instead: my @array = map { [ split ] } @data;
Re: foreach loop with array of arrays
by hardburn (Abbot) on Jun 26, 2003 at 17:56 UTC

    $a and $b are special variables used in sort operations. Avoid using them anywhere else.

    When you create the array, you're not making effective use of how for works. You don't even need that $a varaible. for defaults to putting things in the $_ variable, which is also what split defaults to using. Try:

    for (@data) { push(@{$arrays}, [split(/ /)]); }

    According to the above, you're making $arrays into a scalar that holds a referance to an array of arrays. When you dereferance that, you need to do:

    foreach (@{ $arrays }) { . . . }

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    Note: All code is untested, unless otherwise stated

Re: foreach loop with array of arrays
by Tomte (Priest) on Jun 26, 2003 at 17:57 UTC

    according to the first snippet, $arrays is an array-ref, so you have to dereference it in the second snippet

    foreach(@$arrays) { ... }

    On a second note: you access the elements of @data via subscript, but the for-loop gives you access to the elements during the iteration in the variable $_:

    push(@$arrays, [split(/ /, $_)]) for(@data);
    should be working better; and don't use $a as a variable name, as it has a special meaning.

    regards,
    tomte


    Hlade's Law:

    If you have a difficult task, give it to a lazy person --
    they will find an easier way to do it.

Re: foreach loop with array of arrays
by xdg (Monsignor) on Jun 26, 2003 at 18:04 UTC

    Hardburn is right. And to answer it the other way around, you could also do (using your code):

    push(@arrays, [split(/ /,$data[$a])]);

    I.e., create an array where each element in the array is a reference to an anonymous array. Then you can iterate that array with for (@arrays).

    What you were doing, as Hardburn points out, is creating a scalar reference to an anonymous array, which contained references to anonymous arrays. That's probably overkill for what you intended to do.

    -xdg

    No warranties, express or implied; code may not be tested; Use at your own risk;