Search a list: Difference between revisions

From Rosetta Code
Content added Content deleted
(added Ursala)
(Added R code)
Line 697: Line 697:
>>> </lang>
>>> </lang>

=={{header|R}}==
<lang R>
find.needle <- function(haystack, needle="needle", return.last.index.too=FALSE)
{
indices <- which(haystack %in% needle)
if(length(indices)==0) stop("no needles in the haystack")
if(return.last.index.too) range(indices) else min(indices)
}
</lang>
Example usage:
<lang R>
haystack1 <- c("where", "is", "the", "needle", "I", "wonder")
haystack2 <- c("no", "sewing", "equipment", "in", "here")
haystack3 <- c("oodles", "of", "needles", "needles", "needles", "in", "here")

find.needle(haystack1) # 4
find.needle(haystack2) # error
find.needle(haystack3) # 3
find.needle(haystack3, needle="needles", ret=TRUE) # 3 5
</lang>


=={{header|Ruby}}==
=={{header|Ruby}}==

Revision as of 09:44, 30 July 2009

Task
Search a list
You are encouraged to solve this task according to the task description, using any language you may know.

Find the index of a string (needle) in an indexable, ordered collection of strings (haystack). Raise an exception if the needle is missing. If there is more than one occurrence then return the smallest index to the needle.

As an extra task, return the largest index to a needle that has multiple occurrences in the haystack.

Ada

<lang ada> with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Text_IO; use Ada.Text_IO;

procedure Test_List_Index is

  Not_In : exception;
  
  type List is array (Positive range <>) of Unbounded_String;
  
  function Index (Haystack : List; Needle : String) return Positive is
  begin
     for Index in Haystack'Range loop
        if Haystack (Index) = Needle then
           return Index;
        end if;
     end loop;
     raise Not_In;
  end Index;
     -- Functions to create lists
  function "+" (X, Y : String) return List is
  begin
     return (1 => To_Unbounded_String (X), 2 => To_Unbounded_String (Y));
  end "+";
  
  function "+" (X : List; Y : String) return List is
  begin
     return X & (1 => To_Unbounded_String (Y));
  end "+";
  
  Haystack : List := "Zig"+"Zag"+"Wally"+"Ronald"+"Bush"+"Krusty"+"Charlie"+"Bush"+"Bozo";
  procedure Check (Needle : String) is
  begin
     Put (Needle);
     Put_Line ("at" & Positive'Image (Index (Haystack, Needle)));
  exception
     when Not_In => Put_Line (" is not in");
  end Check;

begin

  Check ("Washington");
  Check ("Bush");

end Test_List_Index; </lang> Sample output:

Washington is not in
Bushat 5

ALGOL 68

Using a FORMAT "value error" exception

FORMAT hay stack := $c("Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo")$;

FILE needle exception; STRING ref needle;
associate(needle exception, ref needle);

PROC index = (FORMAT haystack, REF STRING needle)INT:(
  INT out;
  ref needle := needle;
  getf(needle exception,(haystack, out));
  out
);

[]STRING needles = ("Washington","Bush");
FOR i TO UPB needles DO
  STRING needle := needles[i];
  on value error(needle exception, (REF FILE f)BOOL: value error);
    printf(($d" "gl$,index(hay stack, needle), needle));
    end on value error;
  value error:
    printf(($g" "gl$,needle, "is not in haystack"));
  end on value error: reset(needle exception)
OD

Output:

Washington is not in haystack
5 Bush

Using a manual FOR loop with no exception

[]STRING hay stack = ("Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo");

PROC index = ([]STRING hay stack, STRING needle)INT:(
  INT index;
  FOR i FROM LWB hay stack TO UPB hay stack DO
    index := i;
    IF hay stack[index] = needle THEN
      found
    FI
  OD;
  else:
    LWB hay stack - 1
  EXIT
  found:
    index
);

[]STRING needles = ("Washington","Bush");
FOR i TO UPB needles DO
  STRING needle := needles[i];
  INT result = index(hay stack, needle);
  IF result >= LWB hay stack THEN
    printf(($d" "gl$, result, needle))
  ELSE
    printf(($g" "gl$,needle, "is not in haystack"))
  FI
OD

Output:

Washington is not in haystack
5 Bush

AutoHotkey

<lang AutoHotkey> haystack = Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo needle = bush, washington Loop, Parse, needle, `, {

 If InStr(haystack, A_LoopField)
   MsgBox, % A_LoopField
 Else
   MsgBox % A_LoopField . " not in haystack"

} </lang>

AWK

If we use an awk array indexed with "the order" of the string, to check if the needle is in the haystack we must walk the whole array; if we use the string itself as index (in awk index for an array is indeed an hash), and put its "index" (order number in the list) as associated value, we can fastly check if the needle is in the haystack. But we can't fastly use its order number to get the string value at that position.

In the following implementation we can reach the strings by numeric index with the array haystack_byorder (so, e.g. haystack_byorder[4] gives Bush), and know the "position" of the needle (if it exists) using it as string index for the array haystack, as example does. (Beware: this method does not work when there are duplicates!)

<lang awk>#! /usr/bin/awk -f BEGIN {

   # create the array, using the word as index...
   words="Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo";
   split(words, haystack_byorder, " ");
   j=0;
   for(idx in haystack_byorder) {

haystack[haystack_byorder[idx]] = j; j++;

   }
   # now check for needle (we know it is there, so no "else")...
   if ( "Bush" in haystack ) {

print "Bush is at " haystack["Bush"];

   }
   # check for unexisting needle
   if ( "Washington" in haystack ) {

print "impossible";

   } else {

print "Washington is not here";

   }

}</lang>

C

<lang c>#include <stdio.h>

  1. include <string.h>

const char *haystack[] = {

 "Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie",
 "Bush", "Boz", "Zag", NULL

};

int search_needle(const char *needle, const char **hs) {

 int i = 0;
 while( hs[i] != NULL ) {
   if ( strcmp(hs[i], needle) == 0 ) return i;
   i++;
 }
 return -1;

}

int search_last_needle(const char *needle, const char **hs) {

 int i, last=0;
 i = last = search_needle(needle, hs);
 if ( last < 0 ) return -1;
 while( hs[++i] != NULL ) {
   if ( strcmp(needle, hs[i]) == 0 ) {
     last = i;
   }
 }
 return last;

}

int main() {

 printf("Bush is at %d\n", search_needle("Bush", haystack));
 if ( search_needle("Washington", haystack) == -1 )
   printf("Washington is not in the haystack\n");
 printf("First index for Zag: %d\n", search_needle("Zag", haystack));
 printf("Last index for Zag: %d\n", search_last_needle("Zag", haystack));
 return 0;

}</lang>

Output:

Bush is at 4
Washington is not in the haystack
First index for Zag: 1
Last index for Zag: 9

C++

Works with: g++ version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)

The following code shows three different ways to solve the task.

<lang cpp>

  1. include <string>
  2. include <algorithm>
  3. include <iterator>
  4. include <cstddef>
  5. include <exception>
  6. include <iostream>

// an exception to throw (actually, throwing an exception in this case is generally considered bad style, but it's part of the task) class not_found: public std::exception { public:

 not_found(std::string const& s): text(s + " not found") {}
 char const* what() const throw() { return text.c_str(); }
 ~not_found() throw() {}

private:

 std::string text;

};

// needle search function, C-style interface version using standard library std::size_t get_index(std::string* haystack, int haystack_size, std::string needle) {

 std::size_t index = std::find(haystack, haystack+haystack_size, needle) - haystack;
 if (index == haystack_size)
   throw not_found(needle);
 else
   return index;

}

// needle search function, completely generic style, needs forward iterators // (works with any container, but inefficient if not random-access-iterator) template<typename FwdIter>

typename std::iterator_traits<FwdIter>::difference_type fwd_get_index(FwdIter first, FwdIter last, std::string needle)

{

 FwdIter elem = std::find(first, last, needle);
 if (elem == last)
   throw not_found(needle);
 else
   return std::distance(first, elem);

}

// needle search function, implemented directly, needs only input iterator, works efficiently with all sequences template<typename InIter>

typename std::iterator_traits<InIter>::difference_type generic_get_index(InIter first, InIter last, std::string needle)

{

 typename std::iterator_traits<InIter>::difference_type index = 0;
 while (first != last && *first != needle)
 {
   ++index;
   ++first;
 }
 if (first == last)
   throw not_found(needle);
 else
   return index;

}

// ----------------------------------------------------------------------------------------------------------------------------------

// a sample haystack (content copied from Haskell example) std::string haystack[] = { "Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Bozo" };

// some useful helper functions template<typename T, std::size_t sz> T* begin(T (&array)[sz]) { return array; } template<typename T, std::size_t sz> T* end(T (&array)[sz]) { return array + sz; } template<typename T, std::size_t sz> std::size_t size(T (&array)[sz]) { return sz; }

// test function searching a given needle with each of the methods void test(std::string const& needle) {

 std::cout << "-- C style interface --\n";
 try
 {
   std::size_t index = get_index(haystack, size(haystack), needle);
   std::cout << needle << " found at index " << index << "\n";
 }
 catch(std::exception& exc) // better catch standard exceptions as well; me might e.g. run out of memory
 {
   std::cout << exc.what() << "\n";
 }
 std::cout << "-- generic interface, first version --\n";
 try
 {
   std::size_t index = fwd_get_index(begin(haystack), end(haystack), needle);
   std::cout << needle << " found at index " << index << "\n";
 }
 catch(std::exception& exc) // better catch standard exceptions as well; me might e.g. run out of memory
 {
   std::cout << exc.what() << "\n";
 }
 std::cout << "-- generic interface, second version --\n";
 try
 {
   std::size_t index = generic_get_index(begin(haystack), end(haystack), needle);
   std::cout << needle << " found at index " << index << "\n";
 }
 catch(std::exception& exc) // better catch standard exceptions as well; me might e.g. run out of memory
 {
   std::cout << exc.what() << "\n";
 }

}

int main() {

 std::cout << "\n=== Word which only occurs once ===\n";
 test("Wally");
 std::cout << "\n=== Word occuring multiple times ===\n";
 test("Bush");
 std::cout << "\n=== Word not occuring at all ===\n";
 test("Goofy");

} </lang>

Output (note that in C++, indices start at 0):


=== Word which only occurs once ===
-- C style interface --
Wally found at index 2
-- generic interface, first version --
Wally found at index 2
-- generic interface, second version --
Wally found at index 2

=== Word occuring multiple times ===
-- C style interface --
Bush found at index 4
-- generic interface, first version --
Bush found at index 4
-- generic interface, second version --
Bush found at index 4

=== Word not occuring at all ===
-- C style interface --
Goofy not found
-- generic interface, first version --
Goofy not found
-- generic interface, second version --
Goofy not found

C#

<lang csharp>using System; using System.Collections.Generic;

class Program {

   static void Main(string[] args) {
       List<string> haystack = new List<string>() { "Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Bozo" };
       foreach (string needle in new string[] { "Washington", "Bush" }) {
           int index = haystack.IndexOf(needle);
           
           if (index < 0) Console.WriteLine("{0} is not in haystack",needle);                
           else Console.WriteLine("{0} {1}",index,needle);
       }
   }

}</lang>

Common Lisp

<lang lisp>(let ((haystack '(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo)))

 (dolist (needle '(Washington Bush))
   (let ((index (position needle haystack)))
     (if index
         (progn (print index) (princ needle))
         (progn (print needle) (princ "is not in haystack"))))))</lang>

Output:

WASHINGTON is not in haystack
4 BUSH

E

<lang e>def haystack := ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"]

/** meet the 'raise an exception' requirement */ def find(needle) {

   switch (haystack.indexOf1(needle)) {
       match ==(-1) { throw("an exception") }
       match index { return index }
   }

}

println(find("Ronald")) # prints 3 println(find("McDonald")) # will throw</lang>

Haskell

Libraries and data:

import Data.List

haystack=["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"]
needles = ["Washington","Bush"]

I use 'lambda' notation for readability.

Find 'just' an index:
*Main> map (\x -> (x,elemIndex x haystack)) needles
[("Washington",Nothing),("Bush",Just 4)]

Want to know if there are there more Bushes hiding in the haystack?

*Main> map (\x -> (x,elemIndices x haystack)) needles
[("Washington",[]),("Bush",[4,7])]

To be complete. Here is the 'point free' version of the task:

import Control.Monad
import Control.Arrow
*Main> map (ap (,) (flip elemIndex haystack)) needles
[("Washington",Nothing),("Bush",Just 4)]

J

J has a general and optimized lookup function, i.. For example:

   H =: ;:'Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo'   NB.  Haystack
   N =: ;:'Washington Bush'                                      NB.  Needles
   
   H i. N 
9 3

Note that the arguments to i. can be anything (ie either or both may be scalars, lists, multidimensional arrays, etc).

To format output similar to the other examples, one might write:

   H ;:^:_1@(](>@{:@]|."_1(,.>@{.))i.({;(~:_1+#))1|.'is not in haystack';":&.>@i.@#@[) N
Washington is not in haystack
4 Bush                       

To elaborate a bit: Array-oriented languages (like J) consume the input and produce the output in toto.

That is, all the results are produced simultaneously; consequently, throwing an exception for any part of the input would prohibit producing any output at all.

And while it is both possible and simple to treat the input item by item, this is significantly slower and loses the great advantage of array processing.

Therefore these languages generally produce a special, but conforming, output for "bad" inputs (in this case, an index past the end of the list). Then the functions which consume these outputs may be left untouched (as the special outputs are already in their domain) or may be extended simply.

In this case, there is only one function which formats and prints the results, and its treatment of "good" and "bad" outputs is identical (it cannot distinguish the two). It is simply that the outputs of previous functions have been arranged such that the results are conformable.

Java

for Lists, they have an indexOf() method: <lang java>import java.util.List; import java.util.Arrays;

List<String> haystack = Arrays.asList("Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo");

for (String needle : new String[]{"Washington","Bush"}) {

   int index = haystack.indexOf(needle);
   if (index < 0)
       System.out.println(needle + " is not in haystack");
   else
       System.out.println(index + " " + needle);

}</lang>

for arrays, you have to do it manually: <lang java>String[] haystack = {"Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"};

OUTERLOOP: for (String needle : new String[]{"Washington","Bush"}) {

   for (int i = 0; i < haystack.length; i++)
       if (needle.equals(haystack[i])) {
           System.out.println(i + " " + needle);
           continue OUTERLOOP;
       }
   System.out.println(needle + " is not in haystack");

}</lang>

Output:

Washington is not in haystack
4 Bush

to indexof :item :list
  if empty? :list [(throw "NOTFOUND 0)]
  if equal? :item first :list [output 1]
  output 1 + indexof :item butfirst :list
end

to showindex :item :list
  make "i catch "NOTFOUND [indexof :item :list]
  ifelse :i = 0 [(print :item [ not found in ] :list)] [(print :item [ found at position ] :i [ in ] :list)]
end
showindex "dog [My dog has fleas]   ; dog found at position 2 in My dog has fleas
showindex "cat [My dog has fleas]   ; cat not found in My dog has fleas

Mathematica

This examples shows you the first appearance, the last appearance, and all appearances (as a list): <lang Mathematica>

haystack = {"Zig","Zag","Wally","Ronald","Bush","Zig","Zag","Krusty","Charlie","Bush","Bozo"};
needle = "Zag";
first = Position[haystack,needle,1]1,1
last = Position[haystack,needle,1]-1,1
all = Position[haystack,needle,1]All,1

</lang> gives back: <lang Mathematica>

2
7
{2,7}

</lang>

MAXScript

haystack=#("Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo")

for needle in #("Washington","Bush") do
(
    index = findItem haystack needle
    
    if index == 0 then
    (
        format "% is not in haystack\n" needle
    )
    else
    (
        format "% %\n" index needle
    )
)

Output:

Washington is not in haystack
5 Bush

Objective-C

Works with: Objective-C version 2.0+

<lang objc>NSArray *haystack = [NSArray arrayWithObjects:@"Zig",@"Zag",@"Wally",@"Ronald",@"Bush",@"Krusty",@"Charlie",@"Bush",@"Bozo",nil]; for (id needle in [NSArray arrayWithObjects:@"Washington",@"Bush",nil]) {

   int index = [haystack indexOfObject:needle];
   if (index == NSNotFound)
       NSLog(@"%@ is not in haystack", needle);
   else
       NSLog(@"%i %@", index, needle);

}</lang>

Works with: Objective-C

<lang objc>NSArray *haystack = [NSArray arrayWithObjects:@"Zig",@"Zag",@"Wally",@"Ronald",@"Bush",@"Krusty",@"Charlie",@"Bush",@"Bozo",nil]; id needle; NSEnumerator *enm = [[NSArray arrayWithObjects:@"Washington",@"Bush",nil] objectEnumerator]; while ((needle = [enm nextObject]) != nil) {

   int index = [haystack indexOfObject:needle];
   if (index == NSNotFound)
       NSLog(@"%@ is not in haystack", needle);
   else
       NSLog(@"%i %@", index, needle);

}</lang>

OCaml

# let find_index pred lst =
    let rec loop n = function
       []    -> raise Not_found
     | x::xs -> if pred x then n
                          else loop (n+1) xs
    in
      loop 0 lst;;
val find_index : ('a -> bool) -> 'a list -> int = <fun>
# let haystack = ["Zig";"Zag";"Wally";"Ronald";"Bush";"Krusty";"Charlie";"Bush";"Bozo"];;
val haystack : string list =
  ["Zig"; "Zag"; "Wally"; "Ronald"; "Bush"; "Krusty"; "Charlie"; "Bush";
   "Bozo"]
# List.iter (fun needle ->
               try
                 Printf.printf "%i %s\n" (find_index ((=) needle) haystack) needle
               with Not_found ->
                 Printf.printf "%s is not in haystack\n" needle)
            ["Washington"; "Bush"];;
Washington is not in haystack
4 Bush
- : unit = ()

Perl

<lang perl>use List::Util qw(first);

my @haystack = qw(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo);

foreach my $needle (qw(Washington Bush)) {

 my $index = first { $haystack[$_] eq $needle } (0 .. $#haystack); # note that "eq" was used because we are comparing strings
                                                                   # you would use "==" for numbers
 if (defined $index) {
   print "$index $needle\n";
 } else {
   print "$needle is not in haystack\n";
 }

}</lang> Output:

Washington is not in haystack
4 Bush

You could install a non-standard module List::MoreUtils: <lang perl>use List::MoreUtils qw(first_index);

my @haystack = qw(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo);

foreach my $needle (qw(Washington Bush)) {

 my $index = first_index { $_ eq $needle } @haystack; # note that "eq" was used because we are comparing strings
                                                      # you would use "==" for numbers
 if (defined $index) {
   print "$index $needle\n";
 } else {
   print "$needle is not in haystack\n";
 }

}</lang>

Alternatively, if you need to do this a lot, you could create a hash table mapping values to indices in the haystack: <lang perl>my @haystack = qw(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo);

my %haystack_indices; @haystack_indices{ @haystack } = (0 .. $#haystack); # Caution: this finds the largest index, not the smallest

foreach my $needle (qw(Washington Bush)) {

 my $index = $haystack_indices{$needle};
 if (defined $index) {
   print "$index $needle\n";
 } else {
   print "$needle is not in haystack\n";
 }

}</lang> Output:

Washington is not in haystack
7 Bush

PHP

<lang php>$haystack = array("Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo");

foreach (array("Washington","Bush") as $needle) {

 $i = array_search($needle, $haystack);
 if ($i === FALSE) // note: 0 is also considered false in PHP, so you need to specifically check for FALSE
   echo "$needle is not in haystack\n";
 else
   echo "$i $needle\n";

}</lang> Output:

Washington is not in haystack
4 Bush

Python

<lang python>haystack=["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"]

for needle in ("Washington","Bush"):

 try:
   print haystack.index(needle), needle
 except ValueError, value_error:
   print needle,"is not in haystack"</lang>

Output:

Washington is not in haystack
4 Bush

Note that in Python, the index method of a list already raises an exception. The following shows the default information given when the exception is not captured in the program: <lang python>>>> haystack=["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"] >>> haystack.index('Bush') 4 >>> haystack.index('Washington') Traceback (most recent call last):

 File "<pyshell#95>", line 1, in <module>
   haystack.index('Washington')

ValueError: list.index(x): x not in list >>> </lang>

There is no built-in method for returning the highest index of a repeated string in a Python list, tuple or array, (although strings have rindex). Instead we need to look for the index in the reversed list and adjust the result. <lang python>>>> def hi_index(needle, haystack): return len(haystack)-1 - haystack[::-1].index(needle)

>>> # Lets do some checks >>> for n in haystack: hi = hi_index(n, haystack) assert haystack[hi] == n, "Hi index is of needle" assert n not in haystack[hi+1:], "No higher index exists" if haystack.count(n) == 1: assert hi == haystack.index(n), "index == hi_index if needle occurs only once"


>>> </lang>

R

<lang R> find.needle <- function(haystack, needle="needle", return.last.index.too=FALSE) {

  indices <- which(haystack %in% needle)
  if(length(indices)==0) stop("no needles in the haystack")
  if(return.last.index.too) range(indices) else min(indices)

} </lang> Example usage: <lang R> haystack1 <- c("where", "is", "the", "needle", "I", "wonder") haystack2 <- c("no", "sewing", "equipment", "in", "here") haystack3 <- c("oodles", "of", "needles", "needles", "needles", "in", "here")

find.needle(haystack1) # 4 find.needle(haystack2) # error find.needle(haystack3) # 3 find.needle(haystack3, needle="needles", ret=TRUE) # 3 5 </lang>

Ruby

<lang ruby>haystack= %w(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo)

for needle in %w(Washington Bush) do

 if (i = haystack.index(needle))
   print i, " ", needle, "\n"
 else
   print needle, " is not in haystack\n"
 end

end</lang> Output:

Washington is not in haystack
4 Bush

Slate

<lang slate> define: #haystack -> ('Zig,Zag,Wally,Ronald,Bush,Krusty,Charlie,Bush,Bozo' splitWith: $,). {'Washington'. 'Bush'} do: [| :needle |

 (haystack indexOf: needle)
   ifNil: [inform: word ; ' is not in the haystack']
   ifNotNilDo: [| :firstIndex lastIndex |
     inform: word ; ' is in the haystack at index ' ; firstIndex printString.
     lastIndex: (haystack lastIndexOf: word).
     lastIndex isNotNil /\ (lastIndex > firstIndex) ifTrue:
       [inform: 'last occurrence of ' ; word ; ' is at index ' ; lastIndex]]].

</lang>

Smalltalk

Works with: GNU Smalltalk

Smalltalk indexes start at 1. <lang smalltalk>| haystack | haystack :=

  'Zig,Zag,Wally,Ronald,Bush,Krusty,Charlie,Bush,Bozo' subStrings: $,.

{ 'Washington' . 'Bush' } do: [:i|

 |t l|
 t := (haystack indexOf: i).
 (t = 0) ifTrue: [ ('%1 is not in the haystack' % { i }) displayNl ]
         ifFalse: [ ('%1 is at index %2' % { i . t }) displayNl.
                    l := ( (haystack size) - (haystack reverse indexOf: i) + 1 ).
                    ( t = l ) ifFalse: [ 
                      ('last occurence of %1 is at index %2' % 
                            { i . l }) displayNl ]
                  ]

].</lang>

Standard ML

<lang sml>fun find_index (pred, lst) = let

 fun loop (n, [])    = NONE
   | loop (n, x::xs) = if pred x then SOME n
                                 else loop (n+1, xs)

in

 loop (0, lst)

end;

val haystack = ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"];

app (fn needle =>

      case find_index (fn x => x = needle, haystack) of
           SOME i => print (Int.toString i ^ " " ^ needle ^ "\n")
         | NONE   => print (needle ^ " is not in haystack\n"))
   ["Washington", "Bush"];</lang>

Tcl

<lang tcl>set haystack {Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo} foreach needle {Bush Washington} {

   if {[set idx [lsearch -exact $haystack $needle]] == -1} {
       error "$needle does not appear in the haystack"
   } else {
       puts "$needle appears at index $idx in the haystack"
   }

}</lang> extra credit: <lang tcl>set haystack {Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo} foreach needle {Bush Washington} {

   set indices [lsearch -all -exact $haystack $needle]
   if {[llength $indices] == 0} {
       error "$needle does not appear in the haystack"
   } else {
       puts "$needle appears first at index [lindex $indices 0] and last at [lindex $indices end]" 
   }

}</lang>

Ursala

The indices function takes a pair (needle,haystack) of any type, treats haystack as a list, and returns the pair of indices giving the first and last positions of needle in it, which are numbered from zero and may be equal. If it's not present, an exception is thrown with a diagnostic message of 'missing'. The search is expressed by ~|, the built in distributing filter operator. <lang Ursala>#import std

indices = ||<'missing'>!% ~&nSihzXB+ ~&lrmPE~|^|/~& num</lang> test program: <lang Ursala>#cast %nW

test = indices/'bar' <'foo','bar','baz','bar'></lang> output:

(1,3)