How can I iterate through nested arrays?
I have created an array as follows
while (defined ($line = `<STDIN>`))
{
chomp ($line);
push @stack,($line);
}
eac开发者_高级运维h line has two numbers.
15 6
2 8
how do iterate over each item in each line?
i.e. I want to print
15
6
2
8
I understand it's something like
foreach (@{stack}) (@stack){
print "?????
}
This is where I am stuck.
See the perldsc documentation. That's the Perl Data Structures Cookbook, which has examples for dealing with arrays of arrays. From what you're doing though, it doesn't look like you need an array of arrays.
For your problem of taking two numbers per line and outputting one number per line, just turn the whitespace into newlines:
while( <> ) {
s/\s+/\n/; # turn all whitespace runs into newlines
print; # it's ready to print
}
With Perl 5.10, you can use the new \h
character class that matches only horizontal whitespace:
while( <> ) {
s/\h+/\n/; # turn all horizontal whitespace runs into newlines
print; # it's ready to print
}
As a Perl one-liner, that's just:
% perl -pe 's/\h+/\n/' file.txt
#!/usr/bin/perl
use strict;
use warnings;
while ( my $data = <DATA> ) {
my @values = split ' ', $data;
print $_, "\n" for @values;
}
__DATA__
15 6
2 8
Output:
C:\Temp> h 15 6 2 8
Alternatively, if you want to store each line in @stack
and print out later:
my @stack = map { [ split ] } grep { chomp; length } <DATA>;
The line above slurps everything coming from the DATA
filehandle into a list of lines (because <DATA>
happens in list context). The grep
chomps each line and filters by length after chomping (to avoid getting any trailing empty lines in the data file -- you can avoid it if there are none). The map
then splits each line along spaces, and then creates an anonymous array reference for each line. Finally, such array references are stored in each element of @stack
. You might want to use Data::Dumper
to look at @stack
to understand what's going on.
print join("\n", @$_), "\n" for @stack;
Now, we look over each entry in stack, dereferencing each array in turn, then joining the elements of each array with newlines to print one element per line.
Output:
C:\Temp> h 15 6 2 8
The long way of writing essentially the same thing (with less memory consumption) would be:
my @stack;
while ( my $line = <DATA> ) {
last unless $line =~ /\S/;
my @values = split ' ', $line;
push @stack, \@values;
}
for my $ref ( @stack ) {
print join("\n", @$ref), "\n";
}
Finally, if you wanted do something other than printing all values, say, sum all the numbers, you should store one value per element of @stack
:
use List::Util qw( sum );
my @stack;
while ( my $line = <DATA> ) {
last unless $line =~ /\S/;
my @values = split ' ', $line;
push @stack, @values;
}
printf "The sum is %d\n", sum @stack;
#!/usr/bin/perl
while ($line = <STDIN>) {
chomp ($line);
push @stack, $line;
}
# prints each line
foreach $line (@stack) {
print "$line\n";
}
# splits each line into items using ' ' as separator
# and prints the items
foreach $line (@stack) {
@items = split / /, $line;
foreach $item (@items) {
print $item . "\n";
}
}
I use 'for' for "C" style loops, and 'foreach' for iterating over lists.
#!/usr/bin/perl
use strict;
use warnings;
open IN, "< read.txt" or
die "Can't read in 'read.txt'!";
my $content = join '', <IN>;
while ($content =~ m`(\d+)`g) {
print "$1\n";
}
精彩评论