This is an answer to the updated question, which is about how to iterate through the multidimensional array
Array of arrays
my @mynames = (
[qw(myname mydescription mydata )], # the same as 'myname', 'my...', ...
[qw(myname2 mydescription2 mydata2)],
[qw(myname3 mydescription3 mydata3)],
);
(As the comment states, qw(foo bar)
is just a fancy way to write 'foo', 'bar'
.) This is basically an AoA (array of arrays), which can be used like this:
Dumb iterating
foreach my $row (@mynames) {
foreach my $col (@$row) {
say $col;
}
say 'done with this row';
}
Output:
myname
mydescription
mydata
done with this row
myname2
mydescription2
mydata2
done with this row
myname3
mydescription3
mydata3
done with this row
But we do know a little bit more about this AoA:
Not that dumb iterating
foreach my $row (@mynames) {
say join ', ' => @$row;
}
Output:
myname, mydescription, mydata
myname2, mydescription2, mydata2
myname3, mydescription3, mydata3
$row
is an array reference and to use its list value in join
, we have to dereference it with @$row
. But we can do better:
We know more about the structure here
foreach my $row (@mynames) {
say "name: $row->[0], description: $row->[1], data: $row->[2]";
}
Output:
name: myname, description: mydescription, data: mydata
name: myname2, description: mydescription2, data: mydata2
name: myname3, description: mydescription3, data: mydata3
We know that the first item is a name, the second is a description and the third is some kind of a data value, so we can simply tell the user this fact in our output. $row->[42]
is the way to access a single value in an array ref, compared to do the same with a simple array $array[42]
.
But we can do better!
Hash of hashes
As we know that much about our structure, it's much better to use an hash of hashes (HoH) to express this structure. Since the first item seems to be some kind of a (hopefully unique) name of the rest, we can use it for our hash keys, while description and data go into a new hash reference:
my %data = (
myname => {description => 'foo', data => 42},
myname2 => {description => 'bar', data => 17},
myname3 => {description => 'baz', data => 37},
);
Iterating over the data now feels now much better and the code is more readable and robust:
foreach my $name (keys %data) {
say "name : $name";
say "description: $data{$name}{description}";
say "data : $data{$name}{data}";
}
Output:
name : myname
description: foo
data : 42
name : myname3
description: baz
data : 37
name : myname2
description: bar
data : 17
However, as you can see, the output isn't ordered anymore. Maybe this isn't a problem, but if you want to define an order, you can do it with sort
. With this flexible construct you can for example order by some specific data value:
Order by data
foreach my $name (sort {$data{$a}{data} <=> $data{$b}{data}} keys %data) {
say "name : $name";
say "description: $data{$name}{description}";
say "data : $data{$name}{data}";
}
Output:
name : myname2
description: bar
data : 17
name : myname3
description: baz
data : 37
name : myname
description: foo
data : 42
Read more about how this works in perldoc -f sort.
Array of hashes
If your names aren't unique, you can use an array of hashes like this:
my @data = (
{name => 'myname', description => 'mydescription', data => 'mydata'},
# ...
);
I leave it as a simple exercise for the reader how to operate on this structure. Hope it helps!
More to read
perlreftut - MJD's very short tutorial about references
perlref - Perl references and nested data structures
perldsc - perl data structures cookbook