in reply to looping in 2d array

First of all, in most situations you'll find it much easier to use foreach instead of for. That way, you're letting Perl do all the tedious work with keeping track of indices for you.

Second, as pointed out already, I would consider using a hash instead of an array. Arrays are for looping, hashes are for looking stuff up. I have a very strong gut feeling a data structure containing words will be used mostly for lookups, so let's try to model the data in a way most suitable for the purpose, whatever it is.

Example 1

Consider a hash of hashes. Since I have no idea what the tags 'nn', 'nns' etc. are, I have given them generic names. If naming the tags makes no sense, please just skip this example.

my $words = { 'foo' => { named_property_x => 'nn', named_property_y => 'nns', }, 'bar' => { named_property_x => 'nvbg', named_property_y => 'np', }, }; my $lookup = 'foo'; print $words->{$lookup}->{'named_property_x'}; # Would print 'nn' foreach my $named_property (%{$words->{$lookup}}) { # This would print all the named properties for a specific word, in +no particular order print $named_property . ':' . $words->{$lookup}->{$named_property} . + "\n"; } # To add a new word and/or tag: $words->{'baz'}->{'named_property_z'} = 'nps'; # Do delete a tag delete $words->{'baz'}->{'named_property_z'}; # To check for a specific tag: if ( $words->{'baz'}->{'named_property_z'} eq 'nps' ) { ... }

Example 1

OK so let's say naming the tags makes no sense. Let's instead use a hash of hashes where the tags themselves are used as keys for easy lookup:

my $words = { 'foo' => { nn => 1, nns => 1, }, 'bar' => { nvbg => 1, np => 1, }, }; my $lookup = 'foo'; my $tag = 'nn'; print $words->{$lookup}->{$tag}; # Would print '1' foreach my $tag (keys %{$words->{$lookup}}) { # This would print all the tags for a specified word, in no particul +ar order print $tag . "\n"; } # To add a new word and/or tag: $words->{'baz'}->{'nps'} = 1; # To delete a tag: delete $words->{'baz'}->{'nps'}; # To check for a specific tag: if ( $words->{'baz'}->{'nps'} ) { ... }

Example 3

Now, in your OP the code seems to indicate that the first tag holds a special importance, so let's try a hash of arrays to preserve the order:

my $words = { 'foo' => [ 'nn', 'nns' ], 'bar' => [ 'nvbg', 'np' ], }; my $lookup = 'foo'; print $words->{$lookup}->[0]; # Would print 'nn', the first tag foreach my $tag (@{$words->{$lookup}}) { # This would print the tags for a specified word, in the order in wh +ich they were defined print $tag . "\n"; } # To add a new word and/or tag: push @{$words->{'baz'}}, 'nps'; # To delete a tag: @{$words->{'baz'}} = grep { $_ ne 'nps' } @{$words->{'baz'}}; # To check for a specific tag: if ( grep { $_ eq 'nps' } @{$words->{'baz'}} ) { ... }

Notice that deleting and testing for specific tags now became a little bit trickier.

NOTE: I have not tested this code so it may not even work properly, thus illustrating two points: 1) that arrays are trickier to work with than hashes and 2) don't simply pick one of these examples to work with, they're only meant to give you ideas for different ways to model your data until it fits your needs.

Your best fit is probably not one of these examples anyway, because only you know the actual meaning of your data and how it will be used.

-- FloydATC

Time flies when you don't know what you're doing

Replies are listed 'Best First'.
Re^2: looping in 2d array
by ww (Archbishop) on Nov 02, 2014 at 12:41 UTC

    While I have no inclination to quarrel with FloydATC's code, his statement in para 1 may be misleading (I, for one, find it easier to type 3 letters rather than seven).

    In fact, while some programmers use for and foreach differently, they are indistinguishable except for the spelling ...and either can be used in a C-style loop or a Perlish version with or without an explicit iterator:

    C:\>perl -E "my @arr=qw(a b c d); my $a; for $a(@arr) {say $a;}" a b c d <c>C:\>perl -E "my @arr=qw(a b c d); my $a; foreach $a(@arr) {say $a;} +" a b c d

    And here's brian d foy's response to a question on SO ( http://stackoverflow.com/questions/2279471/whats-the-difference-between-for-and-foreach-in-perl ) back in 2010:

    "They used to be separate ideas, but now they are synonyms. Perl figures out what to do based on what's in the ( ) instead of using the keyword. Blame the people who couldn't type an extra four characters. :)
    C:\>perl -e "foreach ($i=0;$i<10;$i++) { print $i }" # NB: '-e' & 'pri +nt' 0123456789

    And though foy's statement doesn't offer a version or date when "used to be separate ideas" changed, nodes here in the Monastery, back at least as far as 2000, disagree -- some globally, and some only with respect to Perl 4 vs. Perl 5.

    Just for completeness or merely to be excessively didactic :-), if one changes foy's (5.8?) code to my (5.18) "for" ...

    C:>perl -E "for ($i=0;$i<10;$i++) { say $i }" # Irrelevant differences + '-E' & 'say' 0 1 2 3 4 5 6 7 8 9


    Come, let us reason together: Spirit of the Monastery
    -->

      This is true. And beside the point :-)

      My point was to let Perl worry about the incrementing and bounds checking, eliminating many common problems such as accidently using the wrong counter or off-by-one errors. Personally, I find the keyword foreach coupled with a clear, recognizable variable name to be more readable than the for keyword which I'm familiar with from several inferior languages. Although I know perfectly well that Perl will do what I mean either way, I keep a clear distinction between the two to avoid confusion.

      -- FloydATC

      Time flies when you don't know what you're doing

        Sorry if my remark gave offense... but my point is that both for and foreach deal equally well -- and effectively identically -- with Linguist's problem as indicated by the example code in my previous post. Each will cheerfully increment and/or bounds-check (stricken when I engaged brain and realized that I haven't offered an example of bounds-checking in a Perl-style for loop nor can I think of one now) with either C-style or Perlish iterators.

        You believe your mnemonic use of different words is useful to you. I, therefore, believe that para 1 is probably absolutely valid for you. My objection is that para 1 of your earlier post is only a personal opinion (as is this para and the next)... and is phrased in a manner likely to be "misleading" on any question of functionality.

        "Yes," "ja" and "oui" are equivalents even though they are different words ... but addressing a multi-lingual audience it would surely be unwise to suggest that English speakers would be better served in daily life by using "oui" or that Germans should say "oui" or "yes" as an affirmative.


        ++$anecdote ne $data


        This [distinction between for and foreach] is ... beside the point ...

        Given that Linguist identifies him- or herself as "... new to PERL ...", I think ww's point is very apt. As used above, the for versus foreach distinction is a bit of Perl jargon that needs to be identified as such to the novice Perler. If it is not, it leads to questions like "Ok, so what's the difference between for and foreach?" This is a question on a par with "When is a door not a door?", except it has no amusing punchline; instead, there is only the tragic realization that you've just thrown away a few-score seconds of your life pondering a stupid question.

        I had originally not up-voted ww's posts on this point, but have now done so as a show of solidarity forever! against jargon masquerading as idiom.