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

Is it possible to determine an elements indice in an array?

Replies are listed 'Best First'.
(jeffa) Re: Determing the indice of an array
by jeffa (Bishop) on Mar 10, 2003 at 21:46 UTC
    Sure, one way is to create a "reverse lookup" hash via a hash slice:
    my @item = qw(foo bar baz qux); my %lookup = (); @lookup{@item} = (0..$#item); # lookup stuff my $index = $lookup{baz}; print $item[$index], "\n";

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
      That worked perfectly
      Thanks
Re: Determing the indice of an array
by BrowserUk (Patriarch) on Mar 10, 2003 at 22:18 UTC

    It would seem that you already have your answer, but it's worth pointing out that there is one fundemental problem with using a hash to related values in an array with its indices: It fails if you can have duplicate values.

    Given that you need to create the hash to do it, it makes me question if an array is the right structure for your purpose in the first place.

    As you don't give any details of why you want to extablish the index from the value, or what significance that index will have in your program, we cannot speculate on what might be a better approach to the problem, but a voice in the back of my head tells me that given this information, there is a better way.

    Then again, there is another voice in my head telling me that this is a good time to be buying stocks and shares, but I'm studiously ignoring that one.


    Examine what is said, not who speaks.
    1) When a distinguished but elderly scientist states that something is possible, he is almost certainly right. When he states that something is impossible, he is very probably wrong.
    2) The only way of discovering the limits of the possible is to venture a little way past them into the impossible
    3) Any sufficiently advanced technology is indistinguishable from magic.
    Arthur C. Clarke.
Re: Determing the indice of an array
by Wonko the sane (Curate) on Mar 10, 2003 at 22:05 UTC
    Yet another way to do this, without creating a hash lookup would be to just go through each and keep track of what index your on when you find what you are looking for.
    May be better suited if you are dealing with very large arrays.
    #!/usr/local/bin/perl5.6.0 use strict; my $index_of_item; my $item = q{d}; for ( qw| a b c d e f g | ) { ( $_ eq $item ) ? last : $index_of_item++; } print qq{Index of [$item] is [$index_of_item]\n};

    Wonko

      A little heavy. For one thing, it seems safe to assume that they are searching an array, not a constant list. Thus, you don't really need the trinary operator:

      my @ary = (...); my $index; for $index (0 .. $#ary) { last if $ary[$index] eq $val; } print "Index = $index\n";

      (Handling the case of no match is left as an exercise to the reader. Because I'm lazy today.)

      As others have pointed out, conversion to a hash has a lot of drawbacks, not the least of which being the duplicate-value problem and the fact that it just isn't as efficient as travelling the array like above. Converting to a hash is still going to walk the array.

      --rjray

Re: Determing the indice of an array
by BrowserUk (Patriarch) on Mar 11, 2003 at 02:39 UTC

    One further thought. If you really do need to look up an array index from its value using a reverse lookup hash, then it might be better to use the address of the array element rather than the element itself as the hash key, which neatly avoids the problem of duplicates.

    my @a = ('a'..'d','a'..'d') print @a; a b c d a b c d my %a; @a{\(@a)} = 0..$#a; print %a; SCALAR(0x1bd5220) 2 SCALAR(0x1bd5208) 7 SCALAR(0x1bd299c) 5 SCALAR(0x1 +bdf15c) 1 SCALAR(0x1bd5268) 6 SCALAR(0x1bd52c8) 0 SCALAR(0x1bd53b8) 3 SCALAR(0x1 +bd2984) 4 for (@a) { print "$_ has an index of $a{\$_}\n"; } a has an index of 0 b has an index of 1 c has an index of 2 d has an index of 3 a has an index of 4 b has an index of 5 c has an index of 6 d has an index of 7

    Examine what is said, not who speaks.
    1) When a distinguished but elderly scientist states that something is possible, he is almost certainly right. When he states that something is impossible, he is very probably wrong.
    2) The only way of discovering the limits of the possible is to venture a little way past them into the impossible
    3) Any sufficiently advanced technology is indistinguishable from magic.
    Arthur C. Clarke.
      That's fine if you're actually using elements of @a for the lookup, but that rather presupposes that you know where they are to begin with, doesn't it? How about this case?
      my @a = ('a'..'d','a'..'d'); my %a; @a{\(@a)} = 0..$#a; my $x = 'b'; print "$x has an index of $a{\$x}\n"; b has an index of
      Better for the most general case would be to make a lookup hash keyed by the values of the array, with each value of the hash being a reference to an array to which you push the indices from the original array. That way, when you key the hash with an array value, you get every location in the array where that value occurred.