Task[edit]
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.

Extra credit
Return the largest index to a needle that has multiple occurrences in the haystack.

See also
 Search a list of records

/* NetRexx */
options replace format comments java crossref symbols nobinary
 
driver(arg) -- call the test wrapper
return
 
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method searchListOfWords(haystack, needle, forwards = (1 == 1), respectCase = (1 == 1)) public static signals Exception
 
  if \respectCase then do
    needle   = needle.upper()
    haystack = haystack.upper()
    end
  if forwards then wp = haystack.wordpos(needle)
  else             wp = haystack.words() - haystack.reverse().wordpos(needle.reverse()) + 1
  if wp = 0 then signal Exception('*** Error! "'needle'" not found in list ***')
 
  return wp
 
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method searchIndexedList(haystack, needle, forwards = (1 == 1), respectCase = (1 == 1)) public static signals Exception
  if forwards then do
    strtIx = 1
    endIx  = haystack[0]
    incrIx = 1
    end
  else do
    strtIx = haystack[0]
    endIx  = 1
    incrIx = -1
    end
 
    wp = 0
    loop ix = strtIx to endIx by incrIx
      if respectCase then 
        if needle == haystack[ix] then wp = ix
        else nop
      else
        if needle.upper() == haystack[ix].upper() then wp = ix
        else nop
      if wp > 0 then leave ix
      end ix
    if wp = 0 then signal Exception('*** Error! "'needle'" not found in indexed list ***')
 
  return wp
 
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- Test wrapper
method driver(arg) public static
  -- some manifests
  TRUE_        = (1 == 1); FALSE_      = \TRUE_
  FORWARDS_    = TRUE_;    BACKWARDS_  = FALSE_
  CASERESPECT_ = TRUE_;    CASEIGNORE_ = \CASERESPECT_
 
  -- test data
  needles = ['barley', 'quinoa']
 
  -- a simple list of words.  Lists of words are indexable in NetRexx via the word(N) function
  hayrick = 'Barley maize barley sorghum millet wheat rice rye barley Barley oats flax'
 
  -- a Rexx indexed string made up from the words in hayrick
  cornstook = ''
  loop w_ = 1 to hayrick.words() -- populate the indexed string
    cornstook[0]  = w_
    cornstook[w_] = hayrick.word(w_)
    end w_
 
  loop needle over needles
    do -- process the list of words
      say 'Searching for "'needle'" in the list "'hayrick'"'
      idxF = searchListOfWords(hayrick, needle)
      idxL = searchListOfWords(hayrick, needle, BACKWARDS_)
      say '  The first occurence of "'needle'" is at index' idxF 'in the list'
      say '  The last occurence of "'needle'" is at index' idxL 'in the list'
      idxF = searchListOfWords(hayrick, needle, FORWARDS_, CASEIGNORE_)
      idxL = searchListOfWords(hayrick, needle, BACKWARDS_, CASEIGNORE_)
      say '  The first caseless occurence of "'needle'" is at index' idxF 'in the list'
      say '  The last caseless occurence of "'needle'" is at index' idxL 'in the list'
      say
    catch ex = Exception
      say '  'ex.getMessage()
      say
    end
 
    do -- process the indexed list
      corn = ''
      loop ci = 1 to cornstook[0]
        corn = corn cornstook[ci]
        end ci
      say 'Searching for "'needle'" in the indexed list "'corn.space()'"'
      idxF = searchIndexedList(cornstook, needle)
      idxL = searchIndexedList(cornstook, needle, BACKWARDS_)
      say '  The first occurence of "'needle'" is at index' idxF 'in the indexed list'
      say '  The last occurence of "'needle'" is at index' idxL 'in the indexed list'
      idxF = searchIndexedList(cornstook, needle, FORWARDS_, CASEIGNORE_)
      idxL = searchIndexedList(cornstook, needle, BACKWARDS_, CASEIGNORE_)
      say '  The first caseless occurence of "'needle'" is at index' idxF 'in the indexed list'
      say '  The last caseless occurence of "'needle'" is at index' idxL 'in the indexed list'
      say
    catch ex = Exception
      say '  'ex.getMessage()
      say
    end
    end needle
 
  return