Search a list: Difference between revisions
No edit summary |
mNo edit summary |
||
(191 intermediate revisions by 84 users not shown) | |||
Line 1: | Line 1: | ||
{{task|Text processing}} |
{{task|Text processing}} |
||
Find the index of a string (needle) in an indexable, ordered collection of strings (haystack). Raise an exception if the needle is missing. |
|||
{{task heading}} |
|||
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. |
If there is more than one occurrence then return the smallest index to the needle. |
||
{{task heading|Extra credit}} |
|||
As an extra task, return the largest index to a needle that has multiple occurrences in the haystack. |
|||
Return the largest index to a needle that has multiple occurrences in the haystack. |
|||
{{task heading|See also}} |
|||
* [[Search a list of records]] |
|||
<hr> |
|||
=={{header|11l}}== |
|||
{{trans|Python}} |
|||
<syntaxhighlight lang="11l">V haystack = [‘Zig’, ‘Zag’, ‘Wally’, ‘Ronald’, ‘Bush’, ‘Krusty’, ‘Charlie’, ‘Bush’, ‘Bozo’] |
|||
L(needle) (‘Washington’, ‘Bush’) |
|||
X.try |
|||
print(haystack.index(needle)‘ ’needle) |
|||
X.catch ValueError |
|||
print(needle‘ is not in haystack’)</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Washington is not in haystack |
|||
4 Bush |
|||
</pre> |
|||
=={{header|ACL2}}== |
=={{header|ACL2}}== |
||
< |
<syntaxhighlight lang="lisp">(defun index-of-r (e xs i) |
||
(cond ((endp xs) nil) |
(cond ((endp xs) nil) |
||
((equal e (first xs)) i) |
((equal e (first xs)) i) |
||
Line 12: | Line 43: | ||
(defun index-of (e xs) |
(defun index-of (e xs) |
||
(index-of-r e xs 0))</ |
(index-of-r e xs 0))</syntaxhighlight> |
||
=={{header|Acornsoft Lisp}}== |
|||
Acornsoft Lisp does not have strings, so symbols would be used instead. That also allows us to use <code>eq</code> as the test. |
|||
<syntaxhighlight lang="lisp"> |
|||
(defun first-index (word words (i . 0)) |
|||
(loop |
|||
(until (null words) |
|||
(error word '! is! missing)) |
|||
(until (eq word (car words)) |
|||
i) |
|||
(setq words (cdr words)) |
|||
(setq i (add1 i)))) |
|||
(defun last-index (word words (i . 0) (last-i . nil)) |
|||
(loop |
|||
(until (null words) |
|||
(cond (last-i) (t (error word '! is! missing)))) |
|||
(cond ((eq word (car words)) |
|||
(setq last-i i))) |
|||
(setq words (cdr words)) |
|||
(setq i (add1 i)))) |
|||
</syntaxhighlight> |
|||
=={{header|Action!}}== |
|||
<syntaxhighlight lang="action!">DEFINE PTR="CARD" |
|||
INT FUNC Search(PTR ARRAY texts INT count CHAR ARRAY text) |
|||
INT i |
|||
FOR i=0 TO count-1 |
|||
DO |
|||
IF SCompare(texts(i),text)=0 THEN |
|||
RETURN (i) |
|||
FI |
|||
OD |
|||
RETURN (-1) |
|||
PROC Test(PTR ARRAY texts INT count CHAR ARRAY text) |
|||
INT index |
|||
index=Search(texts,count,text) |
|||
IF index=-1 THEN |
|||
PrintF("""%S"" is not in haystack.%E",text) |
|||
ELSE |
|||
PrintF("""%S"" is on index %I in haystack.%E",text,index) |
|||
FI |
|||
RETURN |
|||
PROC Main() |
|||
PTR ARRAY texts(7) |
|||
texts(0)="Monday" |
|||
texts(1)="Tuesday" |
|||
texts(2)="Wednesday" |
|||
texts(3)="Thursday" |
|||
texts(4)="Friday" |
|||
texts(5)="Saturday" |
|||
texts(6)="Sunday" |
|||
Test(texts,7,"Monday") |
|||
Test(texts,7,"Sunday") |
|||
Test(texts,7,"Thursday") |
|||
Test(texts,7,"Weekend") |
|||
RETURN</syntaxhighlight> |
|||
{{out}} |
|||
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Search_a_list.png Screenshot from Atari 8-bit computer] |
|||
<pre> |
|||
"Monday" is on index 0 in haystack. |
|||
"Sunday" is on index 6 in haystack. |
|||
"Thursday" is on index 3 in haystack. |
|||
"Weekend" is not in haystack. |
|||
</pre> |
|||
=={{header|ActionScript}}== |
=={{header|ActionScript}}== |
||
===Using the built-in Error class=== |
===Using the built-in Error class=== |
||
< |
<syntaxhighlight lang="actionscript">var list:Vector.<String> = Vector.<String>(["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Boz", "Zag"]); |
||
function lowIndex(listToSearch:Vector.<String>, searchString:String):int |
function lowIndex(listToSearch:Vector.<String>, searchString:String):int |
||
{ |
{ |
||
Line 31: | Line 136: | ||
throw new Error("String not found: " + searchString); |
throw new Error("String not found: " + searchString); |
||
return index; |
return index; |
||
}</ |
}</syntaxhighlight> |
||
===Using a custom error=== |
===Using a custom error=== |
||
In StringNotFoundError.as: |
In StringNotFoundError.as: |
||
< |
<syntaxhighlight lang="actionscript">package { |
||
public class StringNotFoundError extends Error { |
public class StringNotFoundError extends Error { |
||
public function StringNotFoundError(message:String) { |
public function StringNotFoundError(message:String) { |
||
Line 41: | Line 146: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
In a separate file: |
In a separate file: |
||
< |
<syntaxhighlight lang="actionscript">import StringNotFoundError; |
||
var list:Vector.<String> = Vector.<String>(["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Boz", "Zag"]); |
var list:Vector.<String> = Vector.<String>(["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Boz", "Zag"]); |
||
function lowIndex(listToSearch:Vector.<String>, searchString:String):int |
function lowIndex(listToSearch:Vector.<String>, searchString:String):int |
||
Line 60: | Line 165: | ||
return index; |
return index; |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
< |
<syntaxhighlight lang="ada">with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; |
||
with Ada.Text_IO; use Ada.Text_IO; |
with Ada.Text_IO; use Ada.Text_IO; |
||
Line 103: | Line 209: | ||
Check ("Washington"); |
Check ("Washington"); |
||
Check ("Bush"); |
Check ("Bush"); |
||
end Test_List_Index;</ |
end Test_List_Index;</syntaxhighlight> |
||
{{out}} |
|||
Sample output: |
|||
<pre> |
<pre> |
||
Washington is not in |
Washington is not in |
||
Bushat 5 |
Bushat 5 |
||
</pre> |
</pre> |
||
=={{header|Aime}}== |
|||
<syntaxhighlight lang="aime">void |
|||
search(list l, text s) |
|||
{ |
|||
integer i; |
|||
i = 0; |
|||
while (i < ~l) { |
|||
if (l[i] == s) { |
|||
break; |
|||
} |
|||
i += 1; |
|||
} |
|||
o_(s, " is ", i == ~l ? "not in the haystack" : "at " + itoa(i), "\n"); |
|||
} |
|||
integer |
|||
main(void) |
|||
{ |
|||
list l; |
|||
l = l_effect("Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", |
|||
"Charlie", "Bush", "Boz", "Zag"); |
|||
__ucall(search, 1, 1, l, "Bush", "Washington", "Zag"); |
|||
return 0; |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Bush is at 4 |
|||
Washington is not in the haystack |
|||
Zag is at 1</pre> |
|||
=={{header|ALGOL 68}}== |
=={{header|ALGOL 68}}== |
||
===Using a FORMAT "value error" exception=== |
===Using a FORMAT "value error" exception=== |
||
Line 115: | Line 255: | ||
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-1.18.0/algol68g-1.18.0-9h.tiny.el5.centos.fc11.i386.rpm/download 1.18.0-9h.tiny]}} |
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-1.18.0/algol68g-1.18.0-9h.tiny.el5.centos.fc11.i386.rpm/download 1.18.0-9h.tiny]}} |
||
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - due to extensive use of FORMATted transput}} |
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - due to extensive use of FORMATted transput}} |
||
< |
<syntaxhighlight lang="algol68"> FORMAT hay stack := $c("Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo")$; |
||
FILE needle exception; STRING ref needle; |
FILE needle exception; STRING ref needle; |
||
Line 138: | Line 278: | ||
end on value error: reset(needle exception) |
end on value error: reset(needle exception) |
||
OD |
OD |
||
)</ |
)</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
Washington is not in haystack |
Washington is not in haystack |
||
5 Bush |
5 Bush |
||
</pre> |
</pre> |
||
===Using a manual FOR loop with no exception=== |
===Using a manual FOR loop with no exception=== |
||
{{works with|ALGOL 68|Revision 1 - no extensions to language used}} |
{{works with|ALGOL 68|Revision 1 - no extensions to language used}} |
||
Line 149: | Line 290: | ||
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-1.18.0/algol68g-1.18.0-9h.tiny.el5.centos.fc11.i386.rpm/download 1.18.0-9h.tiny]}} |
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-1.18.0/algol68g-1.18.0-9h.tiny.el5.centos.fc11.i386.rpm/download 1.18.0-9h.tiny]}} |
||
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - due to extensive use of FORMATted transput}} |
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - due to extensive use of FORMATted transput}} |
||
< |
<syntaxhighlight lang="algol68"> []STRING hay stack = ("Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"); |
||
PROC index = ([]STRING hay stack, STRING needle)INT:( |
PROC index = ([]STRING hay stack, STRING needle)INT:( |
||
Line 176: | Line 317: | ||
FI |
FI |
||
OD |
OD |
||
)</ |
)</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
Washington is not in haystack |
Washington is not in haystack |
||
5 Bush |
5 Bush |
||
</pre> |
</pre> |
||
=={{header|Arturo}}== |
|||
<syntaxhighlight lang="rebol">haystack: [Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo] |
|||
loop [Bush Washington] 'needle [ |
|||
i: index haystack needle |
|||
if? empty? i -> panic ~"|needle| is not in haystack" |
|||
else -> print [i needle] |
|||
]</syntaxhighlight> |
|||
{{out}} |
|||
<pre>4 Bush |
|||
>> Error | Washington is not in haystack</pre> |
|||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |
||
< |
<syntaxhighlight lang="autohotkey">haystack = Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo |
||
needle = bush, washington |
needle = bush, washington |
||
Loop, Parse, needle, `, |
Loop, Parse, needle, `, |
||
Line 192: | Line 348: | ||
Else |
Else |
||
MsgBox % A_LoopField . " not in haystack" |
MsgBox % A_LoopField . " not in haystack" |
||
}</ |
}</syntaxhighlight> |
||
=={{header|AWK}}== |
=={{header|AWK}}== |
||
Line 200: | Line 356: | ||
In the following implementation we can reach the strings by numeric index with the array <code>haystack_byorder</code> (so, e.g. <code>haystack_byorder[4]</code> gives Bush), and know the "position" of the needle (if it exists) using it as string index for the array <code>haystack</code>, as example does. ('''Beware''': this method does not work when there are duplicates!) |
In the following implementation we can reach the strings by numeric index with the array <code>haystack_byorder</code> (so, e.g. <code>haystack_byorder[4]</code> gives Bush), and know the "position" of the needle (if it exists) using it as string index for the array <code>haystack</code>, as example does. ('''Beware''': this method does not work when there are duplicates!) |
||
< |
<syntaxhighlight lang="awk">#! /usr/bin/awk -f |
||
BEGIN { |
BEGIN { |
||
# create the array, using the word as index... |
# create the array, using the word as index... |
||
Line 220: | Line 376: | ||
print "Washington is not here"; |
print "Washington is not here"; |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|BASIC}}== |
=={{header|BASIC}}== |
||
{{works with|QBasic}} |
{{works with|QBasic}} |
||
< |
<syntaxhighlight lang="qbasic">DATA foo, bar, baz, quux, quuux, quuuux, bazola, ztesch, foo, bar, thud, grunt |
||
DATA foo, bar, bletch, foo, bar, fum, fred, jim, sheila, barney, flarp, zxc |
DATA foo, bar, bletch, foo, bar, fum, fred, jim, sheila, barney, flarp, zxc |
||
DATA spqr, wombat, shme, foo, bar, baz, bongo, spam, eggs, snork, foo, bar |
DATA spqr, wombat, shme, foo, bar, baz, bongo, spam, eggs, snork, foo, bar |
||
Line 253: | Line 409: | ||
EXIT DO |
EXIT DO |
||
END IF |
END IF |
||
LOOP</ |
LOOP</syntaxhighlight> |
||
{{out}} |
|||
Sample output: |
|||
<pre> |
|||
Word to search for? (Leave blank to exit) foo |
Word to search for? (Leave blank to exit) foo |
||
Found "foo" at index 0 |
Found "foo" at index 0 |
||
Line 274: | Line 431: | ||
Found "baz" at index 29 |
Found "baz" at index 29 |
||
Word to search for? (Leave blank to exit) |
Word to search for? (Leave blank to exit) |
||
</pre> |
|||
==={{header|BASIC256}}=== |
|||
{{trans|Yabasic}} |
|||
<syntaxhighlight lang="freebasic">list$ = "mouse,hat,cup,deodorant,television,soap,methamphetamine,severed cat heads,cup" |
|||
n$ = explode(list$, ",") |
|||
t = 0 : j = 0 |
|||
input string "Enter string to search: ", linea$ |
|||
for i = 0 to n$[?]-1 |
|||
if linea$ = n$[i] then |
|||
if not t then print "First index for "; linea$; ": "; i |
|||
t = i |
|||
j += 1 |
|||
end if |
|||
next |
|||
if t = 0 then |
|||
print "String not found in list" |
|||
else |
|||
if j > 1 then print "Last index for "; linea$; ": "; t |
|||
end if</syntaxhighlight> |
|||
==={{header|BBC BASIC}}=== |
|||
{{works with|BBC BASIC for Windows}} |
|||
<syntaxhighlight lang="bbcbasic"> DIM haystack$(27) |
|||
haystack$() = "alpha","bravo","charlie","delta","echo","foxtrot","golf", \ |
|||
\ "hotel","india","juliet","kilo","lima","mike","needle", \ |
|||
\ "november","oscar","papa","quebec","romeo","sierra","tango", \ |
|||
\ "needle","uniform","victor","whisky","x-ray","yankee","zulu" |
|||
needle$ = "needle" |
|||
maxindex% = DIM(haystack$(), 1) |
|||
FOR index% = 0 TO maxindex% |
|||
IF needle$ = haystack$(index%) EXIT FOR |
|||
NEXT |
|||
IF index% <= maxindex% THEN |
|||
PRINT "First found at index "; index% |
|||
FOR last% = maxindex% TO 0 STEP -1 |
|||
IF needle$ = haystack$(last%) EXIT FOR |
|||
NEXT |
|||
IF last%<>index% PRINT "Last found at index "; last% |
|||
ELSE |
|||
ERROR 100, "Not found" |
|||
ENDIF</syntaxhighlight> |
|||
==={{header|IS-BASIC}}=== |
|||
<syntaxhighlight lang="is-basic">100 PROGRAM "Search.bas" |
|||
110 STRING A$(1 TO 55)*8 |
|||
120 FOR I=1 TO 55 |
|||
130 READ A$(I) |
|||
140 PRINT A$(I);" "; |
|||
150 NEXT |
|||
160 DO |
|||
170 PRINT :INPUT PROMPT "Word to seatch for? (Leave blank to exit) ":S$ |
|||
180 LET S$=LCASE$(LTRIM$(RTRIM$(S$))):LET FOUND=0 |
|||
190 IF S$="" THEN EXIT DO |
|||
200 FOR I=LBOUND(A$) TO UBOUND(A$) |
|||
210 IF A$(I)=S$ THEN LET FOUND=-1:PRINT "Found """;S$;""" at index";I |
|||
220 NEXT |
|||
230 IF NOT FOUND THEN PRINT """";S$;""" not found." |
|||
240 LOOP |
|||
250 DATA foo,bar,baz,quux,quuux,quuuux,bazola,ztesch,foo,bar,thud,grunt,foo,bar,bletch,foo,bar,fum,fred,jim,sheila,barney,flarp,zxc |
|||
260 DATA spqr,wombat,shme,foo,bar,baz,bongo,spam,eggs,snork,foo,bar,zot,blarg,wibble,toto,titi,tata,tutu,pippo,pluto,paperino,aap,noot,mies,oogle,foogle,boogle,zork,gork,bork</syntaxhighlight> |
|||
==={{header|FreeBASIC}}=== |
|||
FreeBASIC doesn't have exceptions so we use a different approach to check if the needle is present or not in the haystack: |
|||
<syntaxhighlight lang="freebasic">' FB 1.05.0 Win64 |
|||
' Works FB 1.05.0 Linux Mint 64 |
|||
Function tryFindString(s() As String, search As String, ByRef index As Integer) As Boolean |
|||
Dim length As Integer = UBound(s) - LBound(s) + 1 |
|||
If length = 0 Then |
|||
index = LBound(s) - 1 '' outside array |
|||
Return False |
|||
End If |
|||
For i As Integer = LBound(s) To UBound(s) |
|||
If s(i) = search Then |
|||
index = i '' first occurrence |
|||
Return True |
|||
End If |
|||
Next |
|||
index = LBound(s) - 1 '' outside array |
|||
Return False |
|||
End Function |
|||
Function tryFindLastString(s() As String, search As String, ByRef index As Integer) As Boolean |
|||
Dim length As Integer = UBound(s) - LBound(s) + 1 |
|||
If length = 0 Then |
|||
index = LBound(s) - 1 '' outside array |
|||
Return False |
|||
End If |
|||
Dim maxIndex As Integer = LBound(s) - 1 '' outside array |
|||
For i As Integer = LBound(s) To UBound(s) |
|||
If s(i) = search Then |
|||
maxIndex = i |
|||
End If |
|||
Next |
|||
If maxIndex > LBound(s) - 1 Then |
|||
index = maxIndex '' last occurrence |
|||
Return True |
|||
Else |
|||
Return False |
|||
End If |
|||
End Function |
|||
Dim haystack(1 To 9) As String = {"Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Bozo"} |
|||
Dim needle(1 To 4) As String = {"Zag", "Krusty", "Washington", "Bush"} |
|||
Dim As Integer index |
|||
Dim As Boolean found |
|||
For i As Integer = 1 To 4 |
|||
found = tryFindString(haystack(), needle(i), index) |
|||
If found Then |
|||
Print needle(i); " found first at index"; index |
|||
Else |
|||
Print needle(i); " is not present" |
|||
End If |
|||
Next |
|||
found = tryFindLastString(haystack(), needle(4), index) |
|||
If found Then |
|||
Print needle(4); " found last at index"; index |
|||
Else |
|||
Print needle(4); " is not present" |
|||
End If |
|||
Print |
|||
Print "Press any key to quit" |
|||
Sleep</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Zag found first at index 2 |
|||
Krusty found first at index 6 |
|||
Washington is not present |
|||
Bush found first at index 5 |
|||
Bush found last at index 8 |
|||
</pre> |
|||
==={{header|Gambas}}=== |
|||
'''[https://gambas-playground.proko.eu/?gist=7729d65f8af3f128db6c6992c5f74e98 Click this link to run this code]''' |
|||
<syntaxhighlight lang="gambas">Public Sub Main() |
|||
Dim sHaystack As String[] = ["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Boz", "Zag"] |
|||
Dim sNeedle As String = "Charlie" |
|||
Dim sOutput As String = "No needle found!" |
|||
Dim siCount As Short |
|||
For siCount = 0 To sHaystack.Max |
|||
If sNeedle = sHaystack[siCount] Then |
|||
sOutPut = sNeedle & " found at index " & Str(siCount) |
|||
Break |
|||
End If |
|||
Next |
|||
Print sOutput |
|||
End</syntaxhighlight> |
|||
Output: |
|||
<pre> |
|||
Charlie found at index 6 |
|||
</pre> |
|||
==={{header|Liberty BASIC}}=== |
|||
<syntaxhighlight lang="lb">haystack$="apple orange pear cherry melon peach banana needle blueberry mango strawberry needle " |
|||
haystack$=haystack$+"pineapple grape kiwi blackberry plum raspberry needle cranberry apricot" |
|||
idx=1 |
|||
do until word$(haystack$,idx)="" |
|||
idx=idx+1 |
|||
loop |
|||
total=idx-1 |
|||
needle$="needle" |
|||
'index of first occurrence |
|||
for i = 1 to total |
|||
if word$(haystack$,i)=needle$ then exit for |
|||
next |
|||
print needle$;" first found at index ";i |
|||
'index of last occurrence |
|||
for j = total to 1 |
|||
if word$(haystack$,j)=needle$ then exit for |
|||
next |
|||
print needle$;" last found at index ";j |
|||
if i<>j then |
|||
print "Multiple instances of ";needle$ |
|||
else |
|||
print "Only one instance of ";needle$;" in list." |
|||
end if |
|||
'raise exception |
|||
needle$="cauliflower" |
|||
for k=1 to total |
|||
if word$(haystack$,k)=needle$ then exit for |
|||
next |
|||
if k>total then |
|||
print needle$;" not found in list." |
|||
else |
|||
print needle$;" found at index ";k |
|||
end if</syntaxhighlight> |
|||
==={{header|PowerBASIC}}=== |
|||
{{works with|PowerBASIC for Windows}} |
|||
<syntaxhighlight lang="powerbasic">FUNCTION PBMAIN () AS LONG |
|||
DIM haystack(54) AS STRING |
|||
ARRAY ASSIGN haystack() = "foo", "bar", "baz", "quux", "quuux", "quuuux", _ |
|||
"bazola", "ztesch", "foo", "bar", "thud", "grunt", "foo", _ |
|||
"bar", "bletch", "foo", "bar", "fum", "fred", "jim", _ |
|||
"sheila", "barney", "flarp", "zxc", "spqr", ";wombat", "shme", _ |
|||
"foo", "bar", "baz", "bongo", "spam", "eggs", "snork", "foo", _ |
|||
"bar", "zot", "blarg", "wibble", "toto", "titi", "tata", _ |
|||
"tutu", "pippo", "pluto", "paperino", "aap", "noot", "mies", _ |
|||
"oogle", "foogle", "boogle", "zork", "gork", "bork" |
|||
DIM needle AS STRING, found AS LONG, lastFound AS LONG |
|||
DO |
|||
needle = INPUTBOX$("Word to search for? (Leave blank to exit)") |
|||
IF needle <> "" THEN |
|||
' collate ucase -> case insensitive |
|||
ARRAY SCAN haystack(), COLLATE UCASE, = needle, TO found |
|||
IF found > 0 THEN |
|||
lastFound = found |
|||
MSGBOX "Found """ & needle & """ at index " & TRIM$(STR$(found - 1)) |
|||
IF found < UBOUND(haystack) THEN |
|||
DO |
|||
ARRAY SCAN haystack(lastFound), COLLATE UCASE, = needle, TO found |
|||
IF found > 0 THEN |
|||
MSGBOX "Another occurence of """ & needle & """ at index " & _ |
|||
TRIM$(STR$(found + lastFound - 1)) |
|||
lastFound = found + lastFound |
|||
ELSE |
|||
MSGBOX "No more occurences of """ & needle & """ found" |
|||
EXIT DO 'will exit inner DO, not outer |
|||
END IF |
|||
LOOP |
|||
END IF |
|||
ELSE |
|||
MSGBOX "No occurences of """ & needle & """ found" |
|||
END IF |
|||
ELSE |
|||
EXIT DO |
|||
END IF |
|||
LOOP |
|||
END FUNCTION</syntaxhighlight> |
|||
==={{header|PureBasic}}=== |
|||
<syntaxhighlight lang="purebasic">If OpenConsole() ; Open a simple console to interact with user |
|||
NewList Straws.s() |
|||
Define Straw$, target$="TBA" |
|||
Define found |
|||
Restore haystack ; Read in all the straws of the haystack. |
|||
Repeat |
|||
Read.s Straw$ |
|||
If Straw$<>"" |
|||
AddElement(Straws()) |
|||
Straws()=UCase(Straw$) |
|||
Continue |
|||
Else |
|||
Break |
|||
EndIf |
|||
ForEver |
|||
While target$<>"" |
|||
Print(#CRLF$+"Enter word to search for (leave blank to quit) :"): target$=Input() |
|||
ResetList(Straws()): found=#False |
|||
While NextElement(Straws()) |
|||
If UCase(target$)=Straws() |
|||
found=#True |
|||
PrintN(target$+" found as index #"+Str(ListIndex(Straws()))) |
|||
EndIf |
|||
Wend |
|||
If Not found |
|||
PrintN("Not found.") |
|||
EndIf |
|||
Wend |
|||
EndIf |
|||
DataSection |
|||
haystack: |
|||
Data.s "Zig","Zag","Zig","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo","" |
|||
EndDataSection</syntaxhighlight> |
|||
==={{header|Run BASIC}}=== |
|||
<syntaxhighlight lang="runbasic">haystack$ = ("Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo Bush ") |
|||
needle$ = "Zag Wally Bush Chicken" |
|||
while word$(needle$,i+1," ") <> "" |
|||
i = i + 1 |
|||
thisNeedle$ = word$(needle$,i," ") + " " |
|||
j = instr(haystack$,thisNeedle$) |
|||
k1 = 0 |
|||
k = instr(haystack$,thisNeedle$,j+1) |
|||
while k <> 0 |
|||
k1 = k |
|||
k = instr(haystack$,thisNeedle$,k+1) |
|||
wend |
|||
if j <> 0 then |
|||
print thisNeedle$;" located at:";j; |
|||
if k1 <> 0 then print " Last position located at:";k1; |
|||
print |
|||
else |
|||
print thisNeedle$;" is not in the list" |
|||
end if |
|||
wend</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Zag located at:5 |
|||
Wally located at:9 |
|||
Bush located at:22 Last position located at:52 |
|||
Chicken is not in the list</pre> |
|||
==={{header|Yabasic}}=== |
|||
<syntaxhighlight lang="yabasic">list$ = "mouse,hat,cup,deodorant,television,soap,methamphetamine,severed cat heads,cup" |
|||
dim item$(1) |
|||
n = token(list$, item$(), ",") |
|||
line input "Enter string to search: " line$ |
|||
for i = 1 to n |
|||
if line$ = item$(i) then |
|||
if not t print "First index for ", line$, ": ", i |
|||
t = i |
|||
j = j + 1 |
|||
end if |
|||
next |
|||
if t = 0 then |
|||
print "String not found in list" |
|||
else |
|||
if j > 1 print "Last index for ", line$, ": ", t |
|||
end if</syntaxhighlight> |
|||
=={{header|Batch File}}== |
|||
The index of this simple implementation is 1-based. The "haystack" data are borrowed from the [[Search_a_list#BASIC|BASIC]] implementation. |
|||
<syntaxhighlight lang="dos">@echo off |
|||
setlocal enabledelayedexpansion |
|||
%==Sample list==% |
|||
set "data=foo, bar, baz, quux, quuux, quuuux, bazola, ztesch, foo, bar, thud, grunt" |
|||
set "data=%data% foo, bar, bletch, foo, bar, fum, fred, jim, sheila, barney, flarp, zxc" |
|||
set "data=%data% spqr, wombat, shme, foo, bar, baz, bongo, spam, eggs, snork, foo, bar" |
|||
set "data=%data% zot, blarg, wibble, toto, titi, tata, tutu, pippo, pluto, paperino, aap" |
|||
set "data=%data% noot, mies, oogle, foogle, boogle, zork, gork, bork" |
|||
%==Sample "needles" [whitespace is the delimiter]==% |
|||
set "needles=foo bar baz jim bong" |
|||
%==Counting and Seperating each Data==% |
|||
set datalen=0 |
|||
for %%. in (!data!) do ( |
|||
set /a datalen+=1 |
|||
set data!datalen!=%%. |
|||
) |
|||
%==Do the search==% |
|||
for %%A in (!needles!) do ( |
|||
set "first=" |
|||
set "last=" |
|||
set "found=0" |
|||
for /l %%B in (1,1,%datalen%) do ( |
|||
if "!data%%B!" == "%%A" ( |
|||
set /a found+=1 |
|||
if !found! equ 1 set first=%%B |
|||
set last=%%B |
|||
) |
|||
) |
|||
if !found! equ 0 echo."%%A": Not found. |
|||
if !found! equ 1 echo."%%A": Found once in index [!first!]. |
|||
if !found! gtr 1 echo."%%A": Found !found! times. First instance:[!first!] Last instance:[!last!]. |
|||
) |
|||
%==We are done==% |
|||
echo. |
|||
pause</syntaxhighlight> |
|||
{{Out}} |
|||
<pre>"foo": Found 6 times. First instance:[1] Last instance:[35]. |
|||
"bar": Found 6 times. First instance:[2] Last instance:[36]. |
|||
"baz": Found 2 times. First instance:[3] Last instance:[30]. |
|||
"jim": Found once in index [20]. |
|||
"bong": Not found. |
|||
Press any key to continue . . .</pre> |
|||
=={{header|BQN}}== |
|||
Generally, <code>⊐</code> (Index Of) is used to find the indices of the right argument array's elements in the left argument. It returns the length of the left argument <code>𝕨</code> if the argument is not present. |
|||
The given <code>IndexOf</code> function is written to satisfy question requirements (throwing exceptions), and it is not recommended for use in production. |
|||
<syntaxhighlight lang="bqn">list ← ⟨"Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Boz", "Zag"⟩ |
|||
IndexOf ← { |
|||
("Error: '" ∾𝕩∾ "' Not found in list") ! (≠𝕨)≠ind ← ⊑𝕨⊐⋈𝕩 |
|||
ind |
|||
} |
|||
•Show list ⊐ "Wally"‿"Hi" # intended |
|||
•Show list IndexOf "Wally" |
|||
list IndexOf "Hi"</syntaxhighlight><syntaxhighlight lang="text">⟨ 2 10 ⟩ |
|||
2 |
|||
! "Error: 'Hi' Not found in list" |
|||
("Error: '" ∾𝕩∾ "' Not found in list") ! (≠𝕨)≠ind ← ⊑𝕨⊐⋈𝕩 |
|||
^ |
|||
list IndexOf "Hi" |
|||
^^^^^^^</syntaxhighlight> |
|||
=={{header|Bracmat}}== |
|||
For both subtasks, pattern matching is used. The second subtasks proceeds in two steps. First, the first word that occurs twice is found (if it exists). Then, the last occurrence of this word is found using forced backtracking (see the <code>~</code> node) until failure. |
|||
<syntaxhighlight lang="bracmat">( return the largest index to a needle that has multiple |
|||
occurrences in the haystack and print the needle |
|||
: ?list |
|||
& ( !list:? haystack [?index ? |
|||
& out$("The word 'haystack' occurs at 1-based index" !index) |
|||
| out$"The word 'haystack' does not occur" |
|||
) |
|||
& ( !list |
|||
: ? %@?needle ? !needle ? |
|||
: ( ? !needle [?index (?&~) |
|||
| ? |
|||
& out |
|||
$ ( str |
|||
$ ( "The word '" |
|||
!needle |
|||
"' occurs more than once. The last 1-based index is " |
|||
!index |
|||
) |
|||
) |
|||
) |
|||
| out$"No word occurs more than once." |
|||
) |
|||
);</syntaxhighlight> |
|||
{{out}} |
|||
<pre>The word 'haystack' occurs at 1-based index 14 |
|||
The word 'the' occurs more than once. The last 1-based index is 17</pre> |
|||
=={{header|Burlesque}}== |
|||
<syntaxhighlight lang="burlesque">blsq ) {"Zig" "Zag" "Wally" "Bush" "Ronald" "Bush"}"Bush"Fi |
|||
3</syntaxhighlight> |
|||
If you want all indices: |
|||
<syntaxhighlight lang="burlesque">blsq ) {"Zig" "Zag" "Wally" "Bush" "Ronald" "Bush"}{"Bush"==}fI |
|||
{3 5}</syntaxhighlight> |
|||
=={{header|C}}== |
=={{header|C}}== |
||
< |
<syntaxhighlight lang="c">#include <stdio.h> |
||
#include <string.h> |
#include <string.h> |
||
Line 316: | Line 922: | ||
printf("Last index for Zag: %d\n", search_last_needle("Zag", haystack)); |
printf("Last index for Zag: %d\n", search_last_needle("Zag", haystack)); |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
Output: |
|||
{{out}} |
|||
<pre>Bush is at 4 |
<pre>Bush is at 4 |
||
Washington is not in the haystack |
Washington is not in the haystack |
||
First index for Zag: 1 |
First index for Zag: 1 |
||
Last index for Zag: 9</pre> |
Last index for Zag: 9</pre> |
||
=={{header|C sharp|C#}}== |
|||
<syntaxhighlight 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); |
|||
} |
|||
} |
|||
}</syntaxhighlight> |
|||
=={{header|C++}}== |
=={{header|C++}}== |
||
Line 330: | Line 953: | ||
The following code shows three different ways to solve the task. |
The following code shows three different ways to solve the task. |
||
< |
<syntaxhighlight lang="cpp">#include <string> |
||
#include <algorithm> |
#include <algorithm> |
||
#include <iterator> |
#include <iterator> |
||
Line 441: | Line 1,064: | ||
std::cout << "\n=== Word not occuring at all ===\n"; |
std::cout << "\n=== Word not occuring at all ===\n"; |
||
test("Goofy"); |
test("Goofy"); |
||
}</ |
}</syntaxhighlight> |
||
{{out}} (note that in C++, indices start at 0): |
|||
<pre> |
<pre> |
||
Line 471: | Line 1,094: | ||
</pre> |
</pre> |
||
== |
=== C++11 === |
||
{{works with|g++ version 4.8.4, clang++ version 3.4| "-std=c++11" }} |
|||
<syntaxhighlight lang="cpp">/* new c++-11 features |
|||
* list class |
|||
* initialization strings |
|||
* auto typing |
|||
* lambda functions |
|||
* noexcept |
|||
* find |
|||
* for/in loop |
|||
*/ |
|||
#include <iostream> // std::cout |
|||
#include <algorithm> // std::find |
|||
#include <list> // std::list |
|||
#include <vector> // std::vector |
|||
#include <string> // string::basic_string |
|||
<lang csharp>using System; |
|||
using System.Collections.Generic; |
|||
using namespace std; // saves typing of "std::" before everything |
|||
class Program { |
|||
static void Main(string[] args) { |
|||
List<string> haystack = new List<string>() { "Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Bozo" }; |
|||
int main() |
|||
foreach (string needle in new string[] { "Washington", "Bush" }) { |
|||
{ |
|||
int index = haystack.IndexOf(needle); |
|||
// initialization lists |
|||
// create objects and fully initialize them with given values |
|||
list<string> l { "Zig", "Zag", "Wally", "Homer", "Madge", |
|||
"Watson", "Ronald", "Bush", "Krusty", "Charlie", |
|||
"Bush", "Bush", "Boz", "Zag" }; |
|||
list<string> n { "Bush" , "Obama", "Homer", "Sherlock" }; |
|||
// lambda function with auto typing |
|||
// auto is easier to write than looking up the complicated |
|||
// specialized iterator type that is actually returned. |
|||
// Just know that it returns an iterator for the list at the position found, |
|||
// or throws an exception if s in not in the list. |
|||
// runtime_error is used because it can be initialized with a message string. |
|||
auto contains = [](list<string> l, string s) throw(runtime_error) |
|||
{ |
|||
auto r = find(begin(l), end(l), s ); |
|||
if( r == end(l) ) |
|||
throw runtime_error( s + " not found" ); |
|||
return r; |
|||
}; |
|||
// returns an int vector with the indexes of the search string |
|||
// The & is a "default capture" meaning that it "allows in" |
|||
// the variables that are in scope where it is called by their |
|||
// name to simplify things. |
|||
auto index = [&](list<string> l, string s) noexcept |
|||
{ |
|||
vector<int> index_v; |
|||
int idx = 0; |
|||
for(const string& r : l) |
|||
{ |
|||
if( s.compare(r) == 0 ) // match -- add to vector |
|||
index_v.push_back(idx); |
|||
idx++; |
|||
} |
|||
// even though index_v is local to the lambda function, |
|||
if (index < 0) Console.WriteLine("{0} is not in haystack",needle); |
|||
// c++11 move semantics does what you want and returns it |
|||
else Console.WriteLine("{0} {1}",index,needle); |
|||
// live and intact instead of destroying it or returning a copy. |
|||
} |
|||
// (very efficient for large objects!) |
|||
} |
|||
return index_v; |
|||
}</lang> |
|||
}; |
|||
// range-based for loop |
|||
// s is a read-only reference, not a copy |
|||
for (const string& s : n) // new iteration syntax is simple and intuitive |
|||
{ |
|||
try |
|||
{ |
|||
auto cont = contains( l , s); // checks if there is any match |
|||
if( cont != l.end() ) // found at least one |
|||
{ |
|||
vector<int> vf = index( l, s ); |
|||
cout << "l contains: " << s << " at " ; |
|||
for(auto x : vf) // auto will resolve to int |
|||
{ cout << x << " "; } // if vector is empty this doesn't run |
|||
cout << "\n"; |
|||
} |
|||
} |
|||
catch (const runtime_error& r) // string not found |
|||
{ |
|||
cout << r.what() << "\n"; |
|||
continue; // try next string |
|||
} |
|||
} //for |
|||
return 0; |
|||
} // main |
|||
/* end */</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
l contains: Bush at 7 10 11 |
|||
Obama not found |
|||
l contains: Homer at 3 |
|||
Sherlock not found |
|||
</pre> |
|||
=={{header|Ceylon}}== |
|||
<syntaxhighlight lang="ceylon">shared test void searchAListTask() { |
|||
value haystack = [ |
|||
"Zig", "Zag", "Wally", "Ronald", "Bush", |
|||
"Krusty", "Charlie", "Bush", "Bozo"]; |
|||
assert(exists firstIdx = haystack.firstOccurrence("Bush")); |
|||
assert(exists lastIdx = haystack.lastOccurrence("Bush")); |
|||
assertEquals(firstIdx, 4); |
|||
assertEquals(lastIdx, 7); |
|||
}</syntaxhighlight> |
|||
=={{header|Clojure}}== |
=={{header|Clojure}}== |
||
< |
<syntaxhighlight lang="clojure">(let [haystack ["Zig" "Zag" "Wally" "Ronald" "Bush" "Krusty" "Charlie" "Bush" "Bozo"]] |
||
(let [idx (.indexOf haystack "Zig")] |
(let [idx (.indexOf haystack "Zig")] |
||
(if (neg? idx) |
(if (neg? idx) |
||
(throw (Error. "item not found.")) |
(throw (Error. "item not found.")) |
||
idx)))</ |
idx)))</syntaxhighlight> |
||
Extra credit: Since Clojure vectors implement java.util.List, you can switch .indexOf for .lastIndexOf to find the highest index of your value. |
Extra credit: Since Clojure vectors implement java.util.List, you can switch .indexOf for .lastIndexOf to find the highest index of your value. |
||
=={{header|CLU}}== |
|||
<syntaxhighlight lang="clu">% Search an indexable, ordered collection. |
|||
% The collection needs to provide `indexes' and `fetch'; |
|||
% the element type needs to provide `equal'. |
|||
search = proc [T, U: type] (haystack: T, needle: U) |
|||
returns (int) signals (not_found) |
|||
where T has indexes: itertype (T) yields (int), |
|||
fetch: proctype (T,int) returns (U) signals (bounds), |
|||
U has equal: proctype (U,U) returns (bool) |
|||
for i: int in T$indexes(haystack) do |
|||
if needle = haystack[i] then return (i) end |
|||
end |
|||
signal not_found |
|||
end search |
|||
start_up = proc () |
|||
as = array[string] |
|||
str_search = search[as,string] |
|||
po: stream := stream$primary_output() |
|||
haystack: as := as$ |
|||
["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"] |
|||
needles: as := as$ |
|||
["Ronald","McDonald","Bush","Obama"] |
|||
for needle: string in as$elements(needles) do |
|||
stream$puts(po, needle || ": ") |
|||
stream$putl(po, int$unparse(str_search(haystack,needle))) |
|||
except when not_found: |
|||
stream$putl(po, "not found") |
|||
end |
|||
end |
|||
end start_up</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Ronald: 4 |
|||
McDonald: not found |
|||
Bush: 5 |
|||
Obama: not found</pre> |
|||
=={{header|COBOL}}== |
|||
<syntaxhighlight lang="cobol">*> This is written to COBOL85, which does not include exceptions. |
|||
IDENTIFICATION DIVISION. |
|||
PROGRAM-ID. Search-List. |
|||
DATA DIVISION. |
|||
WORKING-STORAGE SECTION. |
|||
01 haystack-area. |
|||
78 Haystack-Size VALUE 10. |
|||
03 haystack-data. |
|||
05 FILLER PIC X(7) VALUE "Zig". |
|||
05 FILLER PIC X(7) VALUE "Zag". |
|||
05 FILLER PIC X(7) VALUE "Wally". |
|||
05 FILLER PIC X(7) VALUE "Ronald". |
|||
05 FILLER PIC X(7) VALUE "Bush". |
|||
05 FILLER PIC X(7) VALUE "Krusty". |
|||
05 FILLER PIC X(7) VALUE "Charlie". |
|||
05 FILLER PIC X(7) VALUE "Bush". |
|||
05 FILLER PIC X(7) VALUE "Boz". |
|||
05 FILLER PIC X(7) VALUE "Zag". |
|||
03 haystack-table REDEFINES haystack-data. |
|||
05 haystack PIC X(7) OCCURS Haystack-Size TIMES |
|||
INDEXED BY haystack-index. |
|||
01 needle PIC X(7). |
|||
PROCEDURE DIVISION. |
|||
main. |
|||
MOVE "Bush" TO needle |
|||
PERFORM find-needle |
|||
MOVE "Goofy" TO needle |
|||
PERFORM find-needle |
|||
* *> Extra task |
|||
MOVE "Bush" TO needle |
|||
PERFORM find-last-of-needle |
|||
GOBACK |
|||
. |
|||
find-needle. |
|||
SEARCH haystack |
|||
AT END |
|||
DISPLAY needle " not found." |
|||
WHEN haystack (haystack-index) = needle |
|||
DISPLAY "Found " needle " at " haystack-index "." |
|||
END-SEARCH |
|||
. |
|||
find-last-of-needle. |
|||
PERFORM VARYING haystack-index FROM Haystack-Size BY -1 |
|||
UNTIL haystack-index = 0 |
|||
OR haystack (haystack-index) = needle |
|||
END-PERFORM |
|||
IF haystack-index = 0 |
|||
DISPLAY needle " not found." |
|||
ELSE |
|||
DISPLAY "Found last of " needle " at " haystack-index "." |
|||
END-IF |
|||
.</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Found Bush at +000000005. |
|||
Goofy not found. |
|||
Found last of Bush at +000000008. |
|||
</pre> |
|||
=={{header|Common Lisp}}== |
=={{header|Common Lisp}}== |
||
< |
<syntaxhighlight lang="lisp">(let ((haystack '(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo))) |
||
(dolist (needle '(Washington Bush)) |
(dolist (needle '(Washington Bush)) |
||
(let ((index (position needle haystack))) |
(let ((index (position needle haystack))) |
||
(if index |
(if index |
||
(progn (print index) (princ needle)) |
(progn (print index) (princ needle)) |
||
(progn (print needle) (princ "is not in haystack"))))))</ |
(progn (print needle) (princ "is not in haystack"))))))</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
WASHINGTON is not in haystack |
WASHINGTON is not in haystack |
||
4 BUSH |
4 BUSH |
||
</pre> |
</pre> |
||
The position function solves this task elegantly. |
|||
<syntaxhighlight lang="lisp"> |
|||
CL-USER> (defparameter *list* '(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo)) |
|||
*LIST* |
|||
CL-USER> (position 'Bush *list*) |
|||
4 |
|||
CL-USER> (position 'Bush *list* :from-end t) |
|||
7 |
|||
CL-USER> (position 'Washington *list*) |
|||
NIL</syntaxhighlight> |
|||
=={{header|D}}== |
=={{header|D}}== |
||
< |
<syntaxhighlight lang="d">import std.algorithm, std.range, std.string; |
||
auto firstIndex(R, T)(R hay, T needle) { |
auto firstIndex(R, T)(R hay, T needle) { |
||
Line 529: | Line 1,392: | ||
assert(firstIndex(h, "Bush") == 4); |
assert(firstIndex(h, "Bush") == 4); |
||
assert(lastIndex(h, "Bush") == 7); |
assert(lastIndex(h, "Bush") == 7); |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Delphi}}== |
=={{header|Delphi}}== |
||
<syntaxhighlight lang="delphi">program Needle; |
|||
<lang Delphi> |
|||
program Needle; |
|||
{$APPTYPE CONSOLE} |
{$APPTYPE CONSOLE} |
||
Line 569: | Line 1,431: | ||
list.Free; |
list.Free; |
||
end; |
end; |
||
end.</syntaxhighlight> |
|||
end. |
|||
{{out}} |
|||
</lang> |
|||
Output: |
|||
<pre> |
<pre> |
||
3 |
3 |
||
needle |
needle |
||
</pre> |
</pre> |
||
=={{header|DWScript}}== |
|||
<syntaxhighlight lang="delphi">var haystack : array of String = ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"]; |
|||
function Find(what : String) : Integer; |
|||
begin |
|||
Result := haystack.IndexOf(what); |
|||
if Result < 0 then |
|||
raise Exception.Create('not found'); |
|||
end; |
|||
PrintLn(Find("Ronald")); // 3 |
|||
PrintLn(Find('McDonald')); // exception</syntaxhighlight> |
|||
=={{header|E}}== |
=={{header|E}}== |
||
< |
<syntaxhighlight lang="e">def haystack := ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"] |
||
/** meet the 'raise an exception' requirement */ |
/** meet the 'raise an exception' requirement */ |
||
Line 590: | Line 1,465: | ||
println(find("Ronald")) # prints 3 |
println(find("Ronald")) # prints 3 |
||
println(find("McDonald")) # will throw</ |
println(find("McDonald")) # will throw</syntaxhighlight> |
||
=={{header|EasyLang}}== |
|||
<syntaxhighlight lang=easylang> |
|||
haystack$[] = [ "Zig" "Zag" "Wally" "Ronald" "Bush" "Krusty" "Charlie" "Bush" "Boz" "Zag" ] |
|||
# |
|||
func getind needle$ . |
|||
for i to len haystack$[] |
|||
if haystack$[i] = needle$ |
|||
return i |
|||
. |
|||
. |
|||
return 0 |
|||
. |
|||
# arrays are 1 based |
|||
for n$ in [ "Bush" "Washington" ] |
|||
h = getind n$ |
|||
if h = 0 |
|||
print n$ & " not found" |
|||
else |
|||
print n$ & " found at " & h |
|||
. |
|||
. |
|||
</syntaxhighlight> |
|||
=={{header|Ecstasy}}== |
|||
The <code>List</code> type has an <code>indexOf()</code> method, and the <code>Array</code> type is a <code>List</code>: |
|||
<syntaxhighlight lang="ecstasy"> |
|||
module test { |
|||
@Inject Console console; |
|||
void run() { |
|||
String[] haystack = ["this", "needle", "is", "a", "test"]; |
|||
if (Int pos := haystack.indexOf("needle")) { |
|||
console.print($"Found the needle at {pos=}"); |
|||
} else { |
|||
console.print("No needle in the haystack"); |
|||
} |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
x$ xec test |
|||
Found the needle at pos=1 |
|||
</pre> |
|||
=={{header|Elena}}== |
|||
ELENA 6.x : |
|||
<syntaxhighlight lang="elena">import system'routines; |
|||
import extensions; |
|||
public program() |
|||
{ |
|||
var haystack := new string[]{"Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Bozo"}; |
|||
new string[]{"Washington", "Bush"}.forEach::(needle) |
|||
{ |
|||
var index := haystack.indexOfElement(needle); |
|||
if (index == -1) |
|||
{ |
|||
console.printLine(needle," is not in haystack") |
|||
} |
|||
else |
|||
{ |
|||
console.printLine(needle, " - ", index) |
|||
} |
|||
} |
|||
}</syntaxhighlight> |
|||
=={{header|Elixir}}== |
|||
<syntaxhighlight lang="elixir">haystack = ~w(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo) |
|||
Enum.each(~w(Bush Washington), fn needle -> |
|||
index = Enum.find_index(haystack, fn x -> x==needle end) |
|||
if index, do: (IO.puts "#{index} #{needle}"), |
|||
else: raise "#{needle} is not in haystack\n" |
|||
end)</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
4 Bush |
|||
** (RuntimeError) Washington is not in haystack |
|||
search.exs:5: anonymous fn/1 in :elixir_compiler_0.__FILE__/1 |
|||
(elixir) lib/enum.ex:537: Enum."-each/2-lists^foreach/1-0-"/2 |
|||
(elixir) lib/enum.ex:537: Enum.each/2 |
|||
(elixir) lib/code.ex:316: Code.require_file/2 |
|||
</pre> |
|||
=={{header|Emacs Lisp}}== |
|||
<syntaxhighlight lang="lisp"> |
|||
(defun get-index (item list) |
|||
"Return index of first ITEM in LIST. |
|||
Display error message if ITEM is not |
|||
part of LIST." |
|||
(if (seq-position list item) ; if it's in LIST |
|||
(seq-position list item) ; return index |
|||
;; else, provide an error message |
|||
(message "%s is not an element in %s." item list))) |
|||
;; My thanks to Protesileos Stavrou (aka "Prot") for |
|||
;; key ideas for the section below, including reversing |
|||
;; the list in order to easily find the last item in it. |
|||
(defun last-position (item list) |
|||
"Return last ITEM index in LIST." |
|||
;; test if ITEM is in LIST |
|||
(if (seq-position list item) ; if it's in LIST |
|||
(progn |
|||
;; subtract the adjusted length of the list from |
|||
;; the position of ITEM in the reverse of LIST |
|||
(- |
|||
;; 1- corrects for length being 1 based, but seq-position is 0 based |
|||
(1- (length list)) |
|||
;; reverse list because |
|||
;; seq-position searches from beginning of list |
|||
(seq-position (nreverse list) item))) |
|||
(message "%s is not an element in %s." item list))) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
(get-index "cat" '("cat" "cow" "dog")) |
|||
0 (#o0, #x0, ?\C-@) |
|||
(get-index "horse" '("cat" "cow" "dog")) |
|||
horse is not an element in (cat cow dog cat). |
|||
(last-position "cat" '("cat" "cow" "dog" "cat")) |
|||
3 (#o3, #x3, ?\C-c) |
|||
(last-position "horse" '("cat" "cow" "dog" "cat")) |
|||
horse is not an element in (cat cow dog cat). |
|||
</pre> |
|||
=={{header|Erlang}}== |
=={{header|Erlang}}== |
||
Line 596: | Line 1,607: | ||
Erlang lists can be accessed with the function lists:nth/2, which starts at 1 (first element). As such Erlang can be considered 1-indexed for this problem. |
Erlang lists can be accessed with the function lists:nth/2, which starts at 1 (first element). As such Erlang can be considered 1-indexed for this problem. |
||
Note that you could set the indexing to 0 by modifying the function call in pos/2. |
Note that you could set the indexing to 0 by modifying the function call in pos/2. |
||
< |
<syntaxhighlight lang="erlang">-module(index). |
||
-export([main/0]). |
-export([main/0]). |
||
Line 610: | Line 1,621: | ||
print({Needle, undefined}) -> io:format("~s is not in haystack.~n",[Needle]); |
print({Needle, undefined}) -> io:format("~s is not in haystack.~n",[Needle]); |
||
print({Needle, Pos}) -> io:format("~s at position ~p.~n",[Needle,Pos]).</ |
print({Needle, Pos}) -> io:format("~s at position ~p.~n",[Needle,Pos]).</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
Washington is not in haystack. |
Washington is not in haystack. |
||
Line 624: | Line 1,635: | ||
The procedure can be made into a function to search with other strings, take user input and give output of the searched haystack. |
The procedure can be made into a function to search with other strings, take user input and give output of the searched haystack. |
||
< |
<syntaxhighlight lang="euphoria"> |
||
include std/search.e |
include std/search.e |
||
include std/console.e |
include std/console.e |
||
Line 671: | Line 1,682: | ||
--wait for user to press a key to exit |
--wait for user to press a key to exit |
||
any_key() |
any_key() |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
--------------------------------- |
--------------------------------- |
||
Line 701: | Line 1,712: | ||
Press Any Key to continue... |
Press Any Key to continue... |
||
</pre> |
</pre> |
||
=={{header|F_Sharp|F#}}== |
|||
<syntaxhighlight lang="fsharp">List.findIndex (fun x -> x = "bar") ["foo"; "bar"; "baz"; "bar"] // -> 1 |
|||
// A System.Collections.Generic.KeyNotFoundException |
|||
// is raised, if the predicate does not evaluate to |
|||
// true for any list element.</syntaxhighlight> |
|||
=={{header|Factor}}== |
=={{header|Factor}}== |
||
< |
<syntaxhighlight lang="factor">: find-index ( seq elt -- i ) |
||
'[ _ = ] find drop [ "Not found" throw ] unless* ; inline |
'[ _ = ] find drop [ "Not found" throw ] unless* ; inline |
||
: find-last-index ( seq elt -- i ) |
: find-last-index ( seq elt -- i ) |
||
'[ _ = ] find-last drop [ "Not found" throw ] unless* ; inline</ |
'[ _ = ] find-last drop [ "Not found" throw ] unless* ; inline</syntaxhighlight> |
||
( scratchpad ) { "a" "b" "c" "d" "c" } "c" find-index . |
( scratchpad ) { "a" "b" "c" "d" "c" } "c" find-index . |
||
Line 713: | Line 1,730: | ||
( scratchpad ) { "a" "b" "c" "d" "c" } "c" find-last-index . |
( scratchpad ) { "a" "b" "c" "d" "c" } "c" find-last-index . |
||
4 |
4 |
||
=={{header|Forth}}== |
|||
{{works with|4tH|3.61.5}} |
|||
<syntaxhighlight lang="forth">include lib/row.4th |
|||
create haystack |
|||
," Zig" ," Zag" ," Wally" ," Ronald" ," Bush" ," Krusty" ," Charlie" |
|||
," Bush" ," Boz" ," Zag" NULL , |
|||
does> |
|||
dup >r 1 string-key row 2>r type 2r> ." is " |
|||
if r> - ." at " . else r> drop drop ." not found" then cr |
|||
; |
|||
s" Washington" haystack s" Bush" haystack</syntaxhighlight> |
|||
Works with any ANS Forth |
|||
Needs the FMS-SI (single inheritance) library code located here: |
|||
http://soton.mpeforth.com/flag/fms/index.html |
|||
<syntaxhighlight lang="forth">include FMS-SI.f |
|||
include FMS-SILib.f |
|||
${ Dishonest Fake Left Karl Hillary Monica Bubba Hillary Multi-Millionaire } constant haystack |
|||
: needleIndex { addr len $list | cnt -- idx } |
|||
0 to cnt $list uneach: |
|||
begin |
|||
$list each: |
|||
while |
|||
@: addr len compare 0= if cnt exit then |
|||
cnt 1+ to cnt |
|||
repeat true abort" Not found" ; |
|||
: LastIndexOf { addr len $list | cnt last-found -- idx } |
|||
0 to cnt 0 to last-found $list uneach: |
|||
begin |
|||
$list each: |
|||
while |
|||
@: addr len compare 0= if cnt to last-found then |
|||
cnt 1+ to cnt |
|||
repeat |
|||
last-found if last-found |
|||
else true abort" Not found" |
|||
then ; |
|||
s" Hillary" haystack needleIndex . \ => 4 |
|||
s" Hillary" haystack LastIndexOf . \ => 7 |
|||
s" Washington" haystack needleIndex . \ => aborted: Not found |
|||
</syntaxhighlight> |
|||
=={{header|Fortran}}== |
=={{header|Fortran}}== |
||
< |
<syntaxhighlight lang="fortran">program main |
||
program main |
|||
implicit none |
implicit none |
||
Line 751: | Line 1,817: | ||
end subroutine find_needle |
end subroutine find_needle |
||
end program main |
end program main</syntaxhighlight> |
||
</lang> |
|||
=={{header|FutureBasic}}== |
|||
<syntaxhighlight lang="futurebasic"> |
|||
window 1, @"Search a list" |
|||
void local fn MyEnumeratorCallback( array as CFArrayRef, obj as CFTypeRef, index as NSUInteger, stp as ^BOOL, userData as ptr ) |
|||
if ( fn StringIsEqual( obj, userData ) ) |
|||
print obj;@" found at index ";index |
|||
*stp = YES// stop enumeration |
|||
end if |
|||
if ( index == 0 ) then print userData;@" not found" |
|||
end fn |
|||
void local fn DoIt |
|||
CFArrayRef haystack = @[@"Mike",@"Bravo",@"Tango",@"Uniform",@"Golf", |
|||
@"Tango",@"Sierra",@"November",@"Zulu",@"Delta",@"Hotel",@"Juliet"] |
|||
CFStringRef needle = @"Sierra" |
|||
NSInteger index = fn ArrayIndexOfObject( haystack, needle ) |
|||
if ( index != NSNotFound ) |
|||
print needle;@" found at index ";index |
|||
else |
|||
print needle;@" not found" |
|||
end if |
|||
ArrayEnumerateObjectsWithOptions( haystack, NSEnumerationReverse, @fn MyEnumeratorCallback, (ptr)@"Tango" ) |
|||
end fn |
|||
fn DoIt |
|||
HandleEvents |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Sierra found at index 6 |
|||
Tango found at index 5 |
|||
</pre> |
|||
=={{header|GAP}}== |
=={{header|GAP}}== |
||
< |
<syntaxhighlight lang="gap"># First position is built-in |
||
haystack := Eratosthenes(10000);; |
haystack := Eratosthenes(10000);; |
||
needle := 8999;; |
needle := 8999;; |
||
Line 780: | Line 1,884: | ||
# 1 |
# 1 |
||
LastPosition(a, 0); |
LastPosition(a, 0); |
||
# 97</ |
# 97</syntaxhighlight> |
||
See also [[Sieve of Eratosthenes#GAP|Eratosthenes]] and [[Knuth shuffle#GAP|Shuffle]] functions in RosettaCode. |
See also [[Sieve of Eratosthenes#GAP|Eratosthenes]] and [[Knuth shuffle#GAP|Shuffle]] functions in RosettaCode. |
||
=={{header|Groovy}}== |
|||
<lang groovy> |
|||
def haystack = ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"] |
|||
def needles = ["Washington","Bush","Wally"] |
|||
needles.each { needle -> |
|||
def index = haystack.indexOf(needle) |
|||
def lastindex = haystack.lastIndexOf(needle) |
|||
if (index < 0) { |
|||
assert lastindex < 0 |
|||
println needle + " is not in haystack" |
|||
} else { |
|||
println "First index: " + index + " " + needle |
|||
println "Last index: " + lastindex + " " + needle |
|||
} |
|||
} |
|||
</lang> |
|||
Output: |
|||
<pre> |
|||
Washington is not in haystack |
|||
First index: 4 Bush |
|||
Last index: 7 Bush |
|||
First index: 2 Wally |
|||
Last index: 2 Wally |
|||
</pre> |
|||
=={{header|Go}}== |
=={{header|Go}}== |
||
Data used by both examples below. (You can give multiple files to go run, like <tt>$ go run data.go example.go</tt>) |
|||
<lang go> |
|||
package main |
<syntaxhighlight lang="go">package main |
||
import "fmt" |
|||
var haystack = []string{"Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", |
var haystack = []string{"Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", |
||
Line 825: | Line 1,902: | ||
"zork", "gork", "bork", "sodium", "phosphorous", "californium", |
"zork", "gork", "bork", "sodium", "phosphorous", "californium", |
||
"copernicium", "gold", "thallium", "carbon", "silver", "gold", "copper", |
"copernicium", "gold", "thallium", "carbon", "silver", "gold", "copper", |
||
"helium", "sulfur"} |
"helium", "sulfur"}</syntaxhighlight> |
||
===Linear search=== |
|||
<syntaxhighlight lang="go">package main |
|||
import "fmt" |
|||
func main() { |
func main() { |
||
Line 888: | Line 1,969: | ||
} |
} |
||
return -1 |
return -1 |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
Forward search: soap: smallest index = 15 |
Forward search: soap: smallest index = 15 |
||
Line 897: | Line 1,978: | ||
Reverse search for multiples: gold: largest index = 81 |
Reverse search for multiples: gold: largest index = 81 |
||
Reverse search for multiples: fire: no multiple occurrence |
Reverse search for multiples: fire: no multiple occurrence |
||
</pre> |
|||
===Map lookup=== |
|||
More efficient, if you're doing lots of lookups, is to build a map. This example doesn't completely conform to the task but gives the idea that you could store indexes as map values. |
|||
<syntaxhighlight lang="go">package main |
|||
import "fmt" |
|||
func main() { |
|||
m := map[string][]int{} |
|||
for i, needle := range haystack { |
|||
m[needle] = append(m[needle], i) |
|||
} |
|||
for _, n := range []string{"soap", "gold", "fire"} { |
|||
fmt.Println(n, m[n]) |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
soap [15] |
|||
gold [77 81] |
|||
fire [] |
|||
</pre> |
|||
=={{header|Groovy}}== |
|||
<syntaxhighlight lang="groovy">def haystack = ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"] |
|||
def needles = ["Washington","Bush","Wally"] |
|||
needles.each { needle -> |
|||
def index = haystack.indexOf(needle) |
|||
def lastindex = haystack.lastIndexOf(needle) |
|||
if (index < 0) { |
|||
assert lastindex < 0 |
|||
println needle + " is not in haystack" |
|||
} else { |
|||
println "First index: " + index + " " + needle |
|||
println "Last index: " + lastindex + " " + needle |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Washington is not in haystack |
|||
First index: 4 Bush |
|||
Last index: 7 Bush |
|||
First index: 2 Wally |
|||
Last index: 2 Wally |
|||
</pre> |
</pre> |
||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
Libraries and data: |
Libraries and data: |
||
< |
<syntaxhighlight lang="haskell">import Data.List |
||
haystack=["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"] |
haystack=["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"] |
||
needles = ["Washington","Bush"]</ |
needles = ["Washington","Bush"]</syntaxhighlight> |
||
I use 'lambda' notation for readability. |
I use 'lambda' notation for readability. |
||
:Find 'just' an index: |
:Find 'just' an index: |
||
< |
<syntaxhighlight lang="haskell">*Main> map (\x -> (x,elemIndex x haystack)) needles |
||
[("Washington",Nothing),("Bush",Just 4)]</ |
[("Washington",Nothing),("Bush",Just 4)]</syntaxhighlight> |
||
Want to know if there are there more Bushes hiding in the haystack? |
Want to know if there are there more Bushes hiding in the haystack? |
||
< |
<syntaxhighlight lang="haskell">*Main> map (\x -> (x,elemIndices x haystack)) needles |
||
[("Washington",[]),("Bush",[4,7])]</ |
[("Washington",[]),("Bush",[4,7])]</syntaxhighlight> |
||
To be complete. Here is the 'point free' version of the task: |
To be complete. Here is the 'point free' version of the task: |
||
<syntaxhighlight lang="haskell">*Main> ((,) <*> flip elemIndex haystack) <$> needles |
|||
<lang haskell>import Control.Monad |
|||
[("Washington",Nothing),("Bush",Just 4)]</syntaxhighlight> |
|||
import Control.Arrow |
|||
*Main> map (ap (,) (flip elemIndex haystack)) needles |
|||
[("Washington",Nothing),("Bush",Just 4)]</lang> |
|||
=={{header|HicEst}}== |
=={{header|HicEst}}== |
||
< |
<syntaxhighlight lang="hicest">CHARACTER haystack='Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo.' |
||
CHARACTER needle*10 |
CHARACTER needle*10 |
||
Line 937: | Line 2,060: | ||
WRITE(ClipBoard) "Last ", needle, "found in position ", last |
WRITE(ClipBoard) "Last ", needle, "found in position ", last |
||
! Last bush found in position 8 |
! Last bush found in position 8 |
||
ENDIF</ |
ENDIF</syntaxhighlight> |
||
=={{header|Icon}} and {{header|Unicon}}== |
=={{header|Icon}} and {{header|Unicon}}== |
||
<syntaxhighlight lang="icon"> |
|||
<lang Icon> |
|||
link lists |
link lists |
||
Line 965: | Line 2,088: | ||
every i := p!arglist |
every i := p!arglist |
||
return \i |
return \i |
||
end</ |
end</syntaxhighlight> |
||
{{libheader|Icon Programming Library}} |
{{libheader|Icon Programming Library}} |
||
Taken from the public domain Icon Programming Library's [http://www.cs.arizona.edu/icon/library/src/procs/lists.icn lindex in lists] which generates list indices for x of any type |
Taken from the public domain Icon Programming Library's [http://www.cs.arizona.edu/icon/library/src/procs/lists.icn lindex in lists] which generates list indices for x of any type |
||
< |
<syntaxhighlight lang="icon">procedure lindex(lst, x) #: generate indices for items matching x |
||
local i |
local i |
||
Line 975: | Line 2,098: | ||
if lst[i] === x then suspend i |
if lst[i] === x then suspend i |
||
end</ |
end</syntaxhighlight> |
||
{{out}} |
|||
Sample output: |
|||
<pre>needle=Bush is at position 5 in haystack. |
<pre>needle=Bush is at position 5 in haystack. |
||
needle=Bush is at last position 8 in haystack. |
needle=Bush is at last position 8 in haystack. |
||
Line 989: | Line 2,112: | ||
main(list_1 = []) |
main(list_1 = []) |
||
runerr(500,"Washington") from line 7 in haystack.icn</pre> |
runerr(500,"Washington") from line 7 in haystack.icn</pre> |
||
=={{header|Io}}== |
|||
List has a <code>indexOf</code> method which does not raise an exception on lookup failure but returns <code>nil</code> therefore I extend List with a <code>firstIndex</code> method that does raise an exception. I also create a <code>lastIndex</code> extension that finds the last index of a matching object by iterating in reverse over the list. Note that all these methods find any object not just strings. |
|||
<syntaxhighlight lang="io">NotFound := Exception clone |
|||
List firstIndex := method(obj, |
|||
indexOf(obj) ifNil(NotFound raise) |
|||
) |
|||
List lastIndex := method(obj, |
|||
reverseForeach(i,v, |
|||
if(v == obj, return i) |
|||
) |
|||
NotFound raise |
|||
) |
|||
haystack := list("Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo") |
|||
list("Washington","Bush") foreach(needle, |
|||
try( |
|||
write("firstIndex(\"",needle,"\"): ") |
|||
writeln(haystack firstIndex(needle)) |
|||
)catch(NotFound, |
|||
writeln(needle," is not in haystack") |
|||
)pass |
|||
try( |
|||
write("lastIndex(\"",needle,"\"): ") |
|||
writeln(haystack lastIndex(needle)) |
|||
)catch(NotFound, |
|||
writeln(needle," is not in haystack") |
|||
)pass |
|||
)</syntaxhighlight> |
|||
{{out}} |
|||
<pre>firstIndex("Washington"): Washington is not in haystack |
|||
lastIndex("Washington"): Washington is not in haystack |
|||
firstIndex("Bush"): 4 |
|||
lastIndex("Bush"): 7</pre> |
|||
=={{header|J}}== |
=={{header|J}}== |
||
Line 996: | Line 2,155: | ||
For example: |
For example: |
||
< |
<syntaxhighlight lang="j"> Haystack =: ;:'Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo' |
||
Needles =: ;:'Washington Bush' |
Needles =: ;:'Washington Bush' |
||
Line 1,002: | Line 2,161: | ||
9 4 |
9 4 |
||
Haystack i: Needles NB. last positions |
Haystack i: Needles NB. last positions |
||
9 7</ |
9 7</syntaxhighlight> |
||
Note that the arguments to <code>i.</code> can be anything (ie either or both may be scalars, lists, multidimensional arrays, etc). Nonmatches get a result of 1+largest valid index. |
|||
Other search primitives include: |
|||
<code>e.</code> finds whether items are members of a set, returning a bitmask to select the members: |
|||
<syntaxhighlight lang="j"> Needles e. Haystack |
|||
0 1 |
|||
1 2 3 4 5 6 7 8 9 e. 2 3 5 60 |
|||
0 1 1 0 1 0 0 0 0</syntaxhighlight> |
|||
<code>I.</code> finds indices, but performs a binary search (which requires that the list being searched is sorted). This can be useful for finding non-exact matches (the index of the next value is returned for non-exact matches). |
|||
<syntaxhighlight lang="j"> 1 2 3 4 5 6 7 8 9 I. 2 3 5 60 6.66 |
|||
Note that the arguments to <code>i.</code> can be anything (ie either or both may be scalars, lists, multidimensional arrays, etc). |
|||
1 2 4 9 6 |
|||
(;:'eight five four nine one seven six three two') I. ;:'two three five sixty' |
|||
8 7 1 7</syntaxhighlight> |
|||
To format output similar to the other examples, one might write: |
To format output similar to the other examples, one might write: |
||
< |
<syntaxhighlight lang="j"> Haystack ;:^:_1@(] ,. [ ((<'is not in haystack')"_)`(#@[ I.@:= ])`(8!:0@])} i.) Needles |
||
Washington is not in haystack |
Washington is not in haystack |
||
Bush 4</ |
Bush 4</syntaxhighlight> |
||
Or broken up into components and defined as a verb/function for finding the last positions: |
Or broken up into components and defined as a verb/function for finding the last positions: |
||
< |
<syntaxhighlight lang="j"> msg=: (<'is not in haystack')"_ NB. not found message |
||
idxmissing=: #@[ I.@:= ] NB. indices of items not found |
idxmissing=: #@[ I.@:= ] NB. indices of items not found |
||
fmtdata=: 8!:0@] NB. format atoms as boxed strings |
fmtdata=: 8!:0@] NB. format atoms as boxed strings |
||
Line 1,020: | Line 2,195: | ||
Haystack findLastIndex Needles NB. usage |
Haystack findLastIndex Needles NB. usage |
||
Washington is not in haystack |
Washington is not in haystack |
||
Bush 7</ |
Bush 7</syntaxhighlight> |
||
To elaborate a bit: Array-oriented languages (like J) consume the input and produce the output ''in toto''. |
To elaborate a bit: Array-oriented languages (like J) consume the input and produce the output ''in toto''. |
||
Line 1,028: | Line 2,203: | ||
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. |
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, |
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). |
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. |
|||
=={{header|Java}}== |
=={{header|Java}}== |
||
for Lists, they have an indexOf() method: |
for Lists, they have an indexOf() method: |
||
< |
<syntaxhighlight lang="java">import java.util.List; |
||
import java.util.Arrays; |
import java.util.Arrays; |
||
Line 1,045: | Line 2,224: | ||
else |
else |
||
System.out.println(index + " " + needle); |
System.out.println(index + " " + needle); |
||
}</ |
}</syntaxhighlight> |
||
for arrays, you have to do it manually: |
for arrays, you have to do it manually: |
||
<syntaxhighlight lang="java">import java.util.Arrays; |
|||
<lang java>String[] haystack = {"Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"}; |
|||
String[] haystack = { "Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"}; |
|||
OUTERLOOP: |
|||
for (String needle : new String[]{"Washington","Bush"}) { |
for (String needle : new String[]{"Washington","Bush"}) { |
||
int index = Arrays.binarySearch(haystack, needle); |
|||
if (index < 0) |
|||
if (needle.equals(haystack[i])) { |
|||
System.out.println(needle + " is not in haystack"); |
|||
else |
|||
continue OUTERLOOP; |
|||
System.out.println(index + " " + needle); |
|||
} |
|||
}</syntaxhighlight> |
|||
System.out.println(needle + " is not in haystack"); |
|||
}</lang> |
|||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
Washington is not in haystack |
Washington is not in haystack |
||
Line 1,067: | Line 2,246: | ||
=={{header|JavaScript}}== |
=={{header|JavaScript}}== |
||
< |
<syntaxhighlight lang="javascript">var haystack = ['Zig', 'Zag', 'Wally', 'Ronald', 'Bush', 'Krusty', 'Charlie', 'Bush', 'Bozo'] |
||
var needles = ['Bush', 'Washington'] |
var needles = ['Bush', 'Washington'] |
||
Line 1,082: | Line 2,261: | ||
else |
else |
||
throw needles[i] + " does not appear in the haystack" |
throw needles[i] + " does not appear in the haystack" |
||
}</ |
}</syntaxhighlight> |
||
The following {{works with|JavaScript|1.6}}: |
The following {{works with|JavaScript|1.6}}: |
||
< |
<syntaxhighlight lang="javascript">for each (var needle in needles) { |
||
var idx = haystack.indexOf(needle); |
var idx = haystack.indexOf(needle); |
||
if (idx == -1) |
if (idx == -1) |
||
Line 1,102: | Line 2,281: | ||
break |
break |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
Or, generalising enough (in ES5) to allow for varying definitions of the type of match we are looking for: |
|||
<syntaxhighlight lang="javascript">(function () { |
|||
function findIndex(fnPredicate, list) { |
|||
for (var i = 0, lng = list.length; i < lng; i++) { |
|||
if (fnPredicate(list[i])) { |
|||
return i; |
|||
} |
|||
} |
|||
return Error("not found"); |
|||
}; |
|||
// DEFINING A PARTICULAR TYPE OF SEARCH MATCH |
|||
function matchCaseInsensitive(s, t) { |
|||
return s.toLowerCase() === t.toLowerCase(); |
|||
} |
|||
var lstHaystack = [ |
|||
'Zig', 'Zag', 'Wally', 'Ronald', 'Bush', |
|||
'Krusty', 'Charlie', 'Bush', 'Bozo' |
|||
], |
|||
lstReversed = lstHaystack.slice(0).reverse(), |
|||
iLast = lstHaystack.length - 1, |
|||
lstNeedles = ['bush', 'washington']; |
|||
return { |
|||
'first': lstNeedles.map(function (s) { |
|||
return [s, findIndex(function (t) { |
|||
return matchCaseInsensitive(s, t); |
|||
}, |
|||
lstHaystack)]; |
|||
}), |
|||
'last': lstNeedles.map(function (s) { |
|||
var varIndex = findIndex(function (t) { |
|||
return matchCaseInsensitive(s, t); |
|||
}, |
|||
lstReversed); |
|||
return [ |
|||
s, |
|||
typeof varIndex === 'number' ? |
|||
iLast - varIndex : varIndex |
|||
]; |
|||
}) |
|||
} |
|||
})();</syntaxhighlight> |
|||
Output: |
|||
<syntaxhighlight lang="javascript">{ |
|||
"first": [ |
|||
[ |
|||
"bush", |
|||
4 |
|||
], |
|||
[ |
|||
"washington", |
|||
"Error: not found" |
|||
] |
|||
], |
|||
"last": [ |
|||
[ |
|||
"bush", |
|||
7 |
|||
], |
|||
[ |
|||
"washington", |
|||
"Error: not found" |
|||
] |
|||
] |
|||
}</syntaxhighlight> |
|||
=={{header|jq}}== |
|||
The jq index origin is 0. |
|||
The relevant methods for the tasks at hand are index/1 and rindex/1; indices/1 can also be used. |
|||
In the following, the output is shown after the "# =>": |
|||
<syntaxhighlight lang="jq"> |
|||
["a","b","c"] | index("b") |
|||
# => 1 |
|||
["a","b","c","b"] | index("b") |
|||
# => 1 |
|||
["a","b","c","b"] |
|||
| index("x") // error("element not found") |
|||
# => jq: error: element not found |
|||
# Extra task - the last element of an array can be retrieved |
|||
# using `rindex/` or by using -1 as an index into the array produced by `indices/1`: |
|||
["a","b","c","b","d"] | rindex("b") |
|||
# => 3 |
|||
["a","b","c","b","d"] | indices("b")[-1] |
|||
# => 3</syntaxhighlight> |
|||
=={{header|Julia}}== |
|||
{{works with|Julia|0.6}} |
|||
<syntaxhighlight lang="julia">@show findfirst(["no", "?", "yes", "maybe", "yes"], "yes") |
|||
@show indexin(["yes"], ["no", "?", "yes", "maybe", "yes"]) |
|||
@show findin(["no", "?", "yes", "maybe", "yes"], ["yes"]) |
|||
@show find(["no", "?", "yes", "maybe", "yes"] .== "yes")</syntaxhighlight> |
|||
{{out}} |
|||
<pre>findfirst(["no", "?", "yes", "maybe", "yes"], "yes") = 3 |
|||
indexin(["yes"], ["no", "?", "yes", "maybe", "yes"]) = [5] |
|||
findin(["no", "?", "yes", "maybe", "yes"], ["yes"]) = [3, 5] |
|||
find(["no", "?", "yes", "maybe", "yes"] .== "yes") = [3, 5]</pre> |
|||
=={{header|K}}== |
=={{header|K}}== |
||
< |
<syntaxhighlight lang="k"> Haystack:("Zig";"Zag";"Wally";"Ronald";"Bush";"Krusty";"Charlie";"Bush";"Bozo") |
||
Needles:("Washington";"Bush") |
Needles:("Washington";"Bush") |
||
{:[y _in x;(y;x _bin y);(y;"Not Found")]}[Haystack]'Needles </ |
{:[y _in x;(y;x _bin y);(y;"Not Found")]}[Haystack]'Needles </syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
< |
<syntaxhighlight lang="k">(("Washington" |
||
"Not Found") |
"Not Found") |
||
("Bush" |
("Bush" |
||
4))</ |
4))</syntaxhighlight> |
||
Additional: |
|||
Additional: If more than one occurrence ("Bush"), also show position of the last occurrence. Here we use the dyadic verb _sm (string match) instead of _bin (binary search). |
|||
If more than one occurrence ("Bush"), also show position of the last occurrence. |
|||
Here we use the dyadic verb _sm (string match) instead of _bin (binary search). |
|||
< |
<syntaxhighlight lang="k"> Haystack2: Haystack,,"Bush" |
||
Needles2:Needles,,"Zag" |
Needles2:Needles,,"Zag" |
||
{+(x;{:[#&x;,/?(*&x;*|&x);"Not found"]}'+x _sm/:y)}[Needles2;Haystack2]</ |
{+(x;{:[#&x;,/?(*&x;*|&x);"Not found"]}'+x _sm/:y)}[Needles2;Haystack2]</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<syntaxhighlight lang="k">(("Washington" |
|||
<lang K>(("Washington" |
|||
"Not found") |
"Not found") |
||
("Bush" |
("Bush" |
||
4 9) |
4 9) |
||
("Zag" |
("Zag" |
||
1))</ |
1))</syntaxhighlight> |
||
=={{header| |
=={{header|Kotlin}}== |
||
<syntaxhighlight lang="scala">// version 1.0.6 (search_list.kt) |
|||
<lang lb>haystack$="apple orange pear cherry melon peach banana needle blueberry mango strawberry needle " |
|||
haystack$=haystack$+"pineapple grape kiwi blackberry plum raspberry needle cranberry apricot" |
|||
fun main(args: Array<String>) { |
|||
idx=1 |
|||
val haystack = listOf("Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Boz", "Zag") |
|||
do until word$(haystack$,idx)="" |
|||
println(haystack) |
|||
idx=idx+1 |
|||
var needle = "Zag" |
|||
loop |
|||
var index = haystack.indexOf(needle) |
|||
total=idx-1 |
|||
val index2 = haystack.lastIndexOf(needle) |
|||
println("\n'$needle' first occurs at index $index of the list") |
|||
println("'$needle' last occurs at index $index2 of the list\n") |
|||
needle = "Donald" |
|||
index = haystack.indexOf(needle) |
|||
if (index == -1) throw Exception("$needle does not occur in the list") |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
needle$="needle" |
|||
<pre> |
|||
'index of first occurrence |
|||
[Zig, Zag, Wally, Ronald, Bush, Krusty, Charlie, Bush, Boz, Zag] |
|||
for i = 1 to total |
|||
if word$(haystack$,i)=needle$ then exit for |
|||
next |
|||
print needle$;" first found at index ";i |
|||
'index of |
'Zag' first occurs at index 1 of the list |
||
'Zag' last occurs at index 9 of the list |
|||
for j = total to 1 |
|||
if word$(haystack$,j)=needle$ then exit for |
|||
next |
|||
print needle$;" last found at index ";j |
|||
if i<>j then |
|||
print "Multiple instances of ";needle$ |
|||
else |
|||
print "Only one instance of ";needle$;" in list." |
|||
end if |
|||
Exception in thread "main" java.lang.Exception: Donald does not occur in the list |
|||
'raise exception |
|||
at Search_listKt.main(search_list.kt:13) |
|||
needle$="cauliflower" |
|||
</pre> |
|||
for k=1 to total |
|||
if word$(haystack$,k)=needle$ then exit for |
|||
=={{header|Lang5}}== |
|||
next |
|||
<syntaxhighlight lang="lang5">: haystack(*) ['rosetta 'code 'search 'a 'list 'lang5 'code] find-index ; |
|||
if k>total then |
|||
: find-index |
|||
print needle$;" not found in list." |
|||
2dup eq length iota swap select swap drop |
|||
length if swap drop |
|||
else drop " is not in haystack" 2 compress "" join |
|||
then ; |
|||
: ==>search apply ; |
|||
['hello 'code] 'haystack ==>search .</syntaxhighlight> |
|||
{{out}} |
|||
<pre>[ hello is not in haystack |
|||
[ 1 6 ] |
|||
]</pre> |
|||
=={{header|Lasso}}== |
|||
Lasso arrays have a findindex method which returns all matching indexes. [http://lassoguide.com/operations/containers.html?#array] |
|||
<syntaxhighlight lang="lasso">local(haystack) = array('Zig', 'Zag', 'Wally', 'Ronald', 'Bush', 'Krusty', 'Charlie', 'Bush', 'Bozo') |
|||
#haystack->findindex('Bush')->first // 5 |
|||
#haystack->findindex('Bush')->last // 8 |
|||
protect => {^ |
|||
handle_error => {^ error_msg ^} |
|||
fail_if(not #haystack->findindex('Washington')->first,'Washington is not in haystack.') |
|||
^}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
5 |
|||
8 |
|||
Washington is not in haystack.</pre> |
|||
=={{header|Lingo}}== |
|||
<syntaxhighlight lang="lingo">haystack = ["apples", "oranges", "bananas", "oranges"] |
|||
needle = "oranges" |
|||
pos = haystack.getPos(needle) |
|||
if pos then |
|||
put "needle found at index "&pos |
|||
else |
else |
||
put "needle not found in haystack" |
|||
end if |
end if |
||
</lang> |
|||
-- "needle found at index 2"</syntaxhighlight> |
|||
=={{header|Lisaac}}== |
=={{header|Lisaac}}== |
||
< |
<syntaxhighlight lang="lisaac">+ haystack : ARRAY[STRING]; |
||
haystack := "Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo".split; |
haystack := "Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo".split; |
||
"Washington Bush".split.foreach { needle : STRING; |
"Washington Bush".split.foreach { needle : STRING; |
||
Line 1,184: | Line 2,511: | ||
" is not in haystack\n".print; |
" is not in haystack\n".print; |
||
}; |
}; |
||
};</ |
};</syntaxhighlight> |
||
=={{header|Logo}}== |
=={{header|Logo}}== |
||
< |
<syntaxhighlight lang="logo">to indexof :item :list |
||
if empty? :list [(throw "NOTFOUND 0)] |
if empty? :list [(throw "NOTFOUND 0)] |
||
if equal? :item first :list [output 1] |
if equal? :item first :list [output 1] |
||
Line 1,199: | Line 2,526: | ||
showindex "dog [My dog has fleas] ; dog found at position 2 in My dog has fleas |
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</ |
showindex "cat [My dog has fleas] ; cat not found in My dog has fleas</syntaxhighlight> |
||
=={{header|Lua}}== |
=={{header|Lua}}== |
||
< |
<syntaxhighlight lang="lua">list = {"mouse", "hat", "cup", "deodorant", "television", "soap", "methamphetamine", "severed cat heads"} --contents of my desk |
||
item = io.read() |
item = io.read() |
||
Line 1,209: | Line 2,535: | ||
for i,v in ipairs(list) |
for i,v in ipairs(list) |
||
if v == item then print(i) end |
if v == item then print(i) end |
||
end</ |
end</syntaxhighlight> |
||
=={{header|M2000 Interpreter}}== |
|||
Example based on BASIC's example, changed to find only first occurrence, and last if a second exist. We make one inventory queue which can take sane keys, and a second one with all keys in reverse order. Search works with hash table inside inventory. |
|||
Normally we use Exist(inventoryA, "key") and if it is true then we get the value as Eval(inventoryA) without using second search, by temporary use of an index. We can read that index by making a variable to bind a property of COM object (the object under the inventory). |
|||
<syntaxhighlight lang="m2000 interpreter"> |
|||
Module Checkit { |
|||
Flush ' empty stack |
|||
Inventory Queue Haystack= "foo", "bar", "baz", "quux", "quuux", "quuuux", "bazola", "ztesch", "foo", "bar", "thud", "grunt" |
|||
Append Haystack, "foo", "bar", "bletch", "foo", "bar", "fum", "fred", "jim", "sheila", "barney", "flarp", "zxc" |
|||
Append Haystack, "spqr", "wombat", "shme", "foo", "bar", "baz", "bongo", "spam", "eggs", "snork", "foo", "bar" |
|||
Append Haystack, "zot", "blarg", "wibble", "toto", "titi", "tata", "tutu", "pippo", "pluto", "paperino", "aap" |
|||
Append Haystack, "noot", "mies", "oogle", "foogle", "boogle", "zork", "gork", "bork" |
|||
\\ Inventories are objects and we have access to properties using COM model |
|||
With HayStack, "index" as index |
|||
Inventory Queue HayStackRev |
|||
N=Each(HayStack, -1, 1) |
|||
While N { |
|||
Append HayStackRev, Eval$(N, N^) |
|||
} |
|||
With HayStackRev, "index" as indexRev |
|||
Print Len(HayStack) |
|||
Print Len(HayStackRev) |
|||
local needle$ |
|||
\\ Print all elements using columns |
|||
Print haystack |
|||
Repeat { |
|||
Input "Word to search for? (Leave blank to exit) ", needle$ |
|||
If needle$ <> "" Then { |
|||
If Exist(haystackrev,lcase$(needle$) ) Then { |
|||
Print "Found "; CHR$(34); needle$; CHR$(34); " at index "; STR$(len(haystackrev)-indexrev,"") |
|||
If Exist(haystack,lcase$(needle$) ) Then { |
|||
if len(haystackrev)-1<>indexrev+index then { |
|||
Print "Found "; CHR$(34); needle$; CHR$(34); " at index "; STR$(Len(haystack)-index,"") |
|||
} |
|||
} |
|||
} Else Print CHR$(34); needle$; CHR$(34); " not found" |
|||
} Else Exit |
|||
} Always |
|||
} |
|||
CheckIt |
|||
</syntaxhighlight> |
|||
Extra-Extra: Find all occurrences displaying the indexes for each one. |
|||
<syntaxhighlight lang="m2000 interpreter"> |
|||
Module CheckThis { |
|||
Inventory Queue Haystack= "foo", "bar", "baz", "quux", "quuux", "quuuux", "bazola", "ztesch", "foo", "bar", "thud", "grunt" |
|||
Append Haystack, "foo", "bar", "bletch", "foo", "bar", "fum", "fred", "jim", "sheila", "barney", "flarp", "zxc" |
|||
Append Haystack, "spqr", "wombat", "shme", "foo", "bar", "baz", "bongo", "spam", "eggs", "snork", "foo", "bar" |
|||
Append Haystack, "zot", "blarg", "wibble", "toto", "titi", "tata", "tutu", "pippo", "pluto", "paperino", "aap" |
|||
Append Haystack, "noot", "mies", "oogle", "foogle", "boogle", "zork", "gork", "bork" |
|||
\\ Print all list |
|||
Print Haystack |
|||
\\ inventory queue can get same keys |
|||
\\ inventory use hashtable. |
|||
\\ Inventory put same keys in a linked list, so we can found easy |
|||
Do |
|||
Input "Word to search for? (Leave blank press enter to exit) ", needle$ |
|||
if needle$="" then exit |
|||
n=1 |
|||
s$=lcase$(needle$) |
|||
While exist(Haystack, s$, n) |
|||
\\ number, key and position (zero based convert to one based) |
|||
Print n, Eval$(HayStack!), Eval(HayStack!)+1 |
|||
n++ |
|||
End While |
|||
If n=1 Then Print needle$;" not found" |
|||
Always |
|||
} |
|||
CheckThis |
|||
</syntaxhighlight> |
|||
=={{header|Maple}}== |
|||
<syntaxhighlight lang="maple">haystack := ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"]: |
|||
occurences := ListTools:-SearchAll(needle,haystack): |
|||
try |
|||
#first occurence |
|||
printf("The first occurence is at index %d\n", occurences[1]); |
|||
#last occurence, note that StringTools:-SearchAll()retuns a list of all occurences positions |
|||
printf("The last occurence is at index %d\n", occurences[-1]); |
|||
catch : |
|||
print("Erros: Needle not found in the haystack"): |
|||
end try:</syntaxhighlight> |
|||
{{Out|Examples}} |
|||
needle := "Washington": |
|||
<pre>"Needle not found in the haystack"</pre> |
|||
needle := "Bush": |
|||
<pre>The first occurence is at index 5 |
|||
The last occurence is at index 8</pre> |
|||
=={{header|Mathematica}}== |
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
||
This examples shows you the first appearance, the last appearance, and all appearances (as a list): |
This examples shows you the first appearance, the last appearance, and all appearances (as a list): |
||
< |
<syntaxhighlight lang="mathematica">haystack = {"Zig","Zag","Wally","Ronald","Bush","Zig","Zag","Krusty","Charlie","Bush","Bozo"}; |
||
needle = "Zag"; |
needle = "Zag"; |
||
first = Position[haystack,needle,1][[1,1]] |
first = Position[haystack,needle,1][[1,1]] |
||
last = Position[haystack,needle,1][[-1,1]] |
last = Position[haystack,needle,1][[-1,1]] |
||
all = Position[haystack,needle,1][[All,1]]</ |
all = Position[haystack,needle,1][[All,1]]</syntaxhighlight> |
||
gives back: |
gives back: |
||
<syntaxhighlight lang="mathematica">2 |
|||
<lang Mathematica>2 |
|||
7 |
7 |
||
{2,7}</ |
{2,7}</syntaxhighlight> |
||
=={{header|MATLAB}}== |
=={{header|MATLAB}}== |
||
Collections of strings are stored in cell arrays in MATLAB. The solution bellow will only work for a cell array of this construction:< |
Collections of strings are stored in cell arrays in MATLAB. The solution bellow will only work for a cell array of this construction:<syntaxhighlight lang="matlab">stringCollection = {'string1','string2',...,'stringN'}</syntaxhighlight> It will not work for any other construction, for example:<syntaxhighlight lang="matlab">stringCollection = {{'string1'},{'string2'},{...},{'stringN'}}</syntaxhighlight> |
||
searchCollection.m: |
searchCollection.m: |
||
< |
<syntaxhighlight lang="matlab">function index = searchCollection(list,searchItem,firstLast) |
||
%firstLast is a string containing either 'first' or 'last'. The 'first' |
%firstLast is a string containing either 'first' or 'last'. The 'first' |
||
Line 1,239: | Line 2,656: | ||
assert(~isempty(index),['The string ''' searchItem ''' does not exist in this collection of strings.']); |
assert(~isempty(index),['The string ''' searchItem ''' does not exist in this collection of strings.']); |
||
end</ |
end</syntaxhighlight> |
||
{{out}} |
|||
Sample Output: |
|||
< |
<syntaxhighlight lang="matlab">>> list = {'a','b','c','d','e','c','f','c'}; |
||
>> searchCollection(list,'c','first') |
>> searchCollection(list,'c','first') |
||
Line 1,257: | Line 2,674: | ||
>> searchCollection(list,'g','last') |
>> searchCollection(list,'g','last') |
||
??? Error using ==> searchCollection at 11 |
??? Error using ==> searchCollection at 11 |
||
The string 'g' does not exist in this collection of strings.</ |
The string 'g' does not exist in this collection of strings.</syntaxhighlight> |
||
=={{header|Maxima}}== |
|||
<syntaxhighlight lang="maxima">haystack: ["Zig","Zag","Wally","Ronald","Bush","Zig","Zag","Krusty","Charlie","Bush","Bozo"]; |
|||
needle: "Zag"; |
|||
findneedle(needle, haystack, [opt]):=block([idx], |
|||
idx: sublist_indices(haystack, lambda([w], w=needle)), |
|||
if emptyp(idx) then throw('notfound), |
|||
if emptyp(opt) then return(idx), |
|||
opt: first(opt), |
|||
if opt='f then first(idx) else if opt='l then last(idx) else throw('unknownmode));</syntaxhighlight> |
|||
{{out|Usage}} |
|||
<pre>(%i32) catch(findneedle("Zag", haystack, 'f)); |
|||
(%o32) 2 |
|||
(%i33) catch(findneedle("Zag", haystack, 'l)); |
|||
(%o33) 7 |
|||
(%i34) catch(findneedle("Washington", haystack)); |
|||
(%o34) notfound |
|||
(%i35) catch(findneedle("Bush", haystack, 'f)); |
|||
(%o35) 5 |
|||
(%i36) catch(findneedle("Zag", haystack)); |
|||
(%o36) [2, 7] |
|||
(%i37) catch(findneedle("Zag", haystack, 'l)); |
|||
(%o37) 7</pre> |
|||
=={{header|MAXScript}}== |
=={{header|MAXScript}}== |
||
< |
<syntaxhighlight lang="maxscript">haystack=#("Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo") |
||
for needle in #("Washington","Bush") do |
for needle in #("Washington","Bush") do |
||
Line 1,274: | Line 2,716: | ||
format "% %\n" index needle |
format "% %\n" index needle |
||
) |
) |
||
)</ |
)</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
< |
<syntaxhighlight lang="maxscript">Washington is not in haystack |
||
5 Bush</ |
5 Bush</syntaxhighlight> |
||
=={{header|Nanoquery}}== |
|||
{{trans|Python}} |
|||
<syntaxhighlight lang="nanoquery">$haystack = list() |
|||
append $haystack "Zig" "Zag" "Wally" "Ronald" "Bush" "Krusty" "Charlie" |
|||
append $haystack "Bush" "Bozo" |
|||
$needles = list() |
|||
append $needles "Washington" |
|||
append $needles "Bush" |
|||
for ($i = 0) ($i < len($needles)) ($i = $i + 1) |
|||
$needle = $needles[$i] |
|||
try |
|||
// use array lookup syntax to get the index of the needle |
|||
println $haystack[$needle] + " " + $needle |
|||
catch |
|||
println $needle + " is not in haystack" |
|||
end |
|||
end for</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Washington is not in haystack |
|||
4 Bush</pre> |
|||
=={{header|NetRexx}}== |
|||
<syntaxhighlight lang="netrexx">/* 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</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Searching for "barley" in the list "Barley maize barley sorghum millet wheat rice rye barley Barley oats flax" |
|||
The first occurence of "barley" is at index 3 in the list |
|||
The last occurence of "barley" is at index 9 in the list |
|||
The first caseless occurence of "barley" is at index 1 in the list |
|||
The last caseless occurence of "barley" is at index 10 in the list |
|||
Searching for "barley" in the indexed list "Barley maize barley sorghum millet wheat rice rye barley Barley oats flax" |
|||
The first occurence of "barley" is at index 3 in the indexed list |
|||
The last occurence of "barley" is at index 9 in the indexed list |
|||
The first caseless occurence of "barley" is at index 1 in the indexed list |
|||
The last caseless occurence of "barley" is at index 10 in the indexed list |
|||
Searching for "quinoa" in the list "Barley maize barley sorghum millet wheat rice rye barley Barley oats flax" |
|||
*** Error! "quinoa" not found in list *** |
|||
Searching for "quinoa" in the indexed list "Barley maize barley sorghum millet wheat rice rye barley Barley oats flax" |
|||
*** Error! "quinoa" not found in indexed list *** |
|||
</pre> |
|||
=={{header|Nim}}== |
|||
<syntaxhighlight lang="nim">let haystack = ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"] |
|||
for needle in ["Bush", "Washington"]: |
|||
let f = haystack.find(needle) |
|||
if f >= 0: |
|||
echo f, " ", needle |
|||
else: |
|||
raise newException(ValueError, needle & " not in haystack")</syntaxhighlight> |
|||
{{out}} |
|||
<pre>4 Bush |
|||
[...]/search_a_list.nim(8) search_a_list |
|||
Error: unhandled exception: Washington not in haystack [ValueError]</pre> |
|||
=={{header|Objeck}}== |
|||
<syntaxhighlight lang="objeck">use Collection; |
|||
class Test { |
|||
function : Main(args : String[]) ~ Nil { |
|||
haystack := ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"]; |
|||
values := CompareVector->New(); |
|||
each(i : haystack) { |
|||
values->AddBack(haystack[i]->As(Compare)); |
|||
}; |
|||
needles := ["Washington", "Bush"]; |
|||
each(i : needles) { |
|||
values->Has(needles[i]->As(Compare))->PrintLine(); |
|||
}; |
|||
} |
|||
}</syntaxhighlight> |
|||
=={{header|Objective-C}}== |
=={{header|Objective-C}}== |
||
{{works with|Objective-C|2.0+}} |
{{works with|Objective-C|2.0+}} |
||
< |
<syntaxhighlight lang="objc">NSArray *haystack = @[@"Zig",@"Zag",@"Wally",@"Ronald",@"Bush",@"Krusty",@"Charlie",@"Bush",@"Bozo"]; |
||
for (id needle in [ |
for (id needle in @[@"Washington",@"Bush"]) { |
||
int index = [haystack indexOfObject:needle]; |
int index = [haystack indexOfObject:needle]; |
||
if (index == NSNotFound) |
if (index == NSNotFound) |
||
Line 1,289: | Line 2,915: | ||
else |
else |
||
NSLog(@"%i %@", index, needle); |
NSLog(@"%i %@", index, needle); |
||
}</ |
}</syntaxhighlight> |
||
{{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> |
|||
=={{header|Objeck}}== |
|||
<lang objeck> |
|||
use Structure; |
|||
bundle Default { |
|||
class Test { |
|||
function : Main(args : String[]) ~ Nil { |
|||
haystack := ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"]; |
|||
values := CompareVector->New(); |
|||
each(i : haystack) { |
|||
values->AddBack(haystack[i]->As(Compare)); |
|||
}; |
|||
needles := ["Washington", "Bush"]; |
|||
each(i : needles) { |
|||
values->Has(needles[i]->As(Compare))->PrintLine(); |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
</lang> |
|||
=={{header|OCaml}}== |
=={{header|OCaml}}== |
||
< |
<syntaxhighlight lang="ocaml"># let find_index pred lst = |
||
let rec loop n = function |
let rec loop n = function |
||
[] -> raise Not_found |
[] -> raise Not_found |
||
Line 1,348: | Line 2,940: | ||
Washington is not in haystack |
Washington is not in haystack |
||
4 Bush |
4 Bush |
||
- : unit = ()</ |
- : unit = ()</syntaxhighlight> |
||
=={{header|Odin}}== |
|||
<syntaxhighlight lang="odin">package main |
|||
import "core:slice" |
|||
import "core:fmt" |
|||
main :: proc() { |
|||
hay_stack := []string{"Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"} |
|||
// Odin does not support exceptions. |
|||
// For conditions requiring special processing during the execution of a program it is |
|||
// encouraged to make that explicit through return values: |
|||
index, found := slice.linear_search(hay_stack, "Bush") |
|||
if found do fmt.printf("First occurence of 'Bush' at %d\n", index) |
|||
index, found = slice.linear_search(hay_stack, "Rob") |
|||
if found do fmt.printf("First occurence of 'Rob' at %d\n", index) |
|||
} |
|||
// Output: |
|||
// First occurence of 'Bush' at 4</syntaxhighlight> |
|||
=={{header|Oforth}}== |
|||
indexOf returns null if an object is not into a collection, not an exception. |
|||
<syntaxhighlight lang="oforth">: needleIndex(needle, haystack) |
|||
haystack indexOf(needle) dup ifNull: [ drop ExRuntime throw("Not found", needle) ] ; |
|||
[ "Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Boz" ] const: Haystack |
|||
needleIndex("Bush", Haystack) println |
|||
Haystack lastIndexOf("Bush") println |
|||
needleIndex("Washington", Haystack) println</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
5 |
|||
8 |
|||
[1:interpreter] ExRuntime : Not found <Washington> |
|||
</pre> |
|||
=={{header|ooRexx}}== |
|||
All ooRexx collections support an index method that will search for an item. |
|||
For ordered collections, this will always be the first item. |
|||
For unordered collections, the index returned is undetermined. |
|||
<syntaxhighlight lang="oorexx">-- ordered collections always return the first hit |
|||
a = .array~of(1,2,3,4,4,5) |
|||
say a~index(4) |
|||
a2 = .array~new(5,5) -- multidimensional |
|||
a2[3,3] = 4 |
|||
-- the returned index is an array of values |
|||
say a2~index(4)~makestring('line', ',') |
|||
-- Note, list indexes are assigned when an item is added and |
|||
-- are not tied to relative position |
|||
l = .list~of(1,2,3,4,4,5) |
|||
say l~index(4) |
|||
q = .queue~of(1,2,3,4,4,5) |
|||
say q~index(4) |
|||
-- directories are unordered, so it is |
|||
-- undertermined which one is returned |
|||
d = .directory~new |
|||
d["foo"] = 4 |
|||
d["bar"] = 4 |
|||
say d~index(4)</syntaxhighlight> |
|||
=={{header|Oz}}== |
=={{header|Oz}}== |
||
No such function exists for the built-in list type |
No such function exists for the built-in list type |
||
(the operation is quite inefficient, after all). |
|||
<lang oz>declare |
|||
A possible implementation: |
|||
<syntaxhighlight lang="oz">declare |
|||
%% Lazy list of indices of Y in Xs. |
%% Lazy list of indices of Y in Xs. |
||
fun {Indices Y Xs} |
fun {Indices Y Xs} |
||
Line 1,375: | Line 3,037: | ||
{Show {List.last {Indices "Bush" Haystack}}} |
{Show {List.last {Indices "Bush" Haystack}}} |
||
{Show {Index "Washington" Haystack}} %% throws</ |
{Show {Index "Washington" Haystack}} %% throws</syntaxhighlight> |
||
=={{header|PARI/GP}}== |
=={{header|PARI/GP}}== |
||
{{works with|PARI/GP|2.4.3 and above}} |
{{works with|PARI/GP|2.4.3 and above}} |
||
< |
<syntaxhighlight lang="parigp">find(v,n)={ |
||
my(i=setsearch(v,n)); |
my(i=setsearch(v,n)); |
||
if(i, |
if(i, |
||
Line 1,387: | Line 3,049: | ||
); |
); |
||
i |
i |
||
};</ |
};</syntaxhighlight> |
||
=={{header|Pascal}}== |
=={{header|Pascal}}== |
||
Line 1,393: | Line 3,055: | ||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
< |
<syntaxhighlight lang="perl">use List::Util qw(first); |
||
my @haystack = qw(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo); |
my @haystack = qw(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo); |
||
Line 1,405: | Line 3,067: | ||
print "$needle is not in haystack\n"; |
print "$needle is not in haystack\n"; |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
Washington is not in haystack |
Washington is not in haystack |
||
Line 1,413: | Line 3,075: | ||
You could install a non-standard module List::MoreUtils: |
You could install a non-standard module List::MoreUtils: |
||
< |
<syntaxhighlight lang="perl">use List::MoreUtils qw(first_index); |
||
my @haystack = qw(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo); |
my @haystack = qw(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo); |
||
Line 1,425: | Line 3,087: | ||
print "$needle is not in haystack\n"; |
print "$needle is not in haystack\n"; |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
Alternatively, if you need to do this a lot, you could create a hash table mapping values to indices in the haystack: |
Alternatively, if you need to do this a lot, you could create a hash table mapping values to indices in the haystack: |
||
< |
<syntaxhighlight lang="perl">my @haystack = qw(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo); |
||
my %haystack_indices; |
my %haystack_indices; |
||
Line 1,440: | Line 3,102: | ||
print "$needle is not in haystack\n"; |
print "$needle is not in haystack\n"; |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
Washington is not in haystack |
Washington is not in haystack |
||
Line 1,447: | Line 3,109: | ||
</pre> |
</pre> |
||
=={{header| |
=={{header|Phix}}== |
||
{{libheader|Phix/basics}} |
|||
{{works with|Rakudo Star|2010.08}} |
|||
<!--<syntaxhighlight lang="phix">--> |
|||
<span style="color: #008080;">constant</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"Zig"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Zag"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Wally"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Ronald"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Bush"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Krusty"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Charlie"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Bush"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Boz"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"Zag"</span><span style="color: #0000FF;">}</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Zag"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">r</span> <span style="color: #000080;font-style:italic;">-- 2 (first)</span> |
|||
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Zag"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">r</span> <span style="color: #000080;font-style:italic;">-- 10 (next)</span> |
|||
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Zag"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">r</span> <span style="color: #000080;font-style:italic;">-- 0 (no more)</span> |
|||
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">rfind</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Zag"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">r</span> <span style="color: #000080;font-style:italic;">-- 10 (last)</span> |
|||
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Zog"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">r</span> <span style="color: #000080;font-style:italic;">-- 0 (none)</span> |
|||
<!--</syntaxhighlight>--> |
|||
=={{header|Phixmonti}}== |
|||
<lang perl6>sub find ($matcher, $container) { |
|||
<syntaxhighlight lang="phixmonti">"mouse" "hat" "cup" "deodorant" "television" |
|||
for $container.kv -> $k, $v { |
|||
"soap" "methamphetamine" "severed cat heads" "cup" |
|||
$v ~~ $matcher and return $k; |
|||
pstack |
|||
} |
|||
stklen tolist reverse |
|||
fail 'No values matched'; |
|||
0 tolist var t |
|||
} |
|||
"Enter string to search: " input var s nl |
|||
my Str @haystack = <Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo>; |
|||
true |
|||
while |
|||
head s == if |
|||
len t swap 0 put var t |
|||
endif |
|||
tail nip len |
|||
endwhile |
|||
drop |
|||
t len not if |
|||
for <Washingston Bush> -> $needle { |
|||
"String not found in list" print |
|||
my $pos = find $needle, @haystack; |
|||
else |
|||
if defined $pos { |
|||
reverse |
|||
say "Found '$needle' at index $pos"; |
|||
"First index for " print s print " : " print 1 get print |
|||
say 'Largest index: ', @haystack.end - |
|||
len 1 > if |
|||
find { $needle eq $^x }, reverse @haystack; |
|||
nl "Last index for " print s print " : " print len get print |
|||
} |
|||
endif |
|||
endif |
|||
say "'$needle' not in haystack"; |
|||
drop</syntaxhighlight> |
|||
} |
|||
}</lang> |
|||
Other solution with syntactic sugar for list construction. |
|||
The <code>~~</code> operator does smart matching based on the type of the matcher; in the general case, you can pass any predicate you like to force the semantics one way or another. |
|||
<syntaxhighlight lang="phixmonti">include Utilitys.pmt |
|||
0 var acum |
|||
0 var p |
|||
"Zag" var word |
|||
def search |
|||
word find var p p |
|||
enddef |
|||
( "Zig" "Zag" "Wally" "Ronald" "Bush" "Krusty" "Charlie" "Bush" "Boz" "Zag" ) |
|||
dup print nl nl |
|||
search |
|||
while |
|||
p acum + var acum |
|||
( word " located in position " acum ) lprint nl |
|||
len p - p 1 + swap slice nip |
|||
search |
|||
endwhile |
|||
</syntaxhighlight> |
|||
=={{header|PHP}}== |
=={{header|PHP}}== |
||
< |
<syntaxhighlight lang="php">$haystack = array("Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"); |
||
foreach (array("Washington","Bush") as $needle) { |
foreach (array("Washington","Bush") as $needle) { |
||
Line 1,481: | Line 3,183: | ||
else |
else |
||
echo "$i $needle\n"; |
echo "$i $needle\n"; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
Washington is not in haystack |
Washington is not in haystack |
||
4 Bush |
4 Bush |
||
</pre> |
</pre> |
||
=={{header|Picat}}== |
|||
Picat has built-in functions <code>find_first_of/2</code> and <code>find_last_of/2</code>. They return -1 if the needle is not found, so here they are wrapped in functions that throws exceptions in this case. |
|||
And Picat is 1-based. |
|||
<syntaxhighlight lang="picat">import util. |
|||
go => |
|||
Haystack=["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Bush", "Charlie", "Bush", "Boz", "Zag"], |
|||
println("First 'Bush'"=search_list(Haystack,"Bush")), |
|||
println("Last 'Bush'"=search_list_last(Haystack,"Bush")), |
|||
println("All 'Bush'"=search_list_all(Haystack,"Bush")), |
|||
catch(WaldoIx=search_list(Haystack,"Waldo"),E,println(E)), |
|||
println("Waldo"=WaldoIx), |
|||
nl. |
|||
% Wrapping find_first_of/2 and find_last_of/2 with exceptions |
|||
search_list(Haystack,Needle) = Ix => |
|||
Ix = find_first_of(Haystack,Needle), |
|||
if Ix < 0 then |
|||
throw $error(search_list(Needle),not_found) |
|||
end. |
|||
search_list_last(Haystack,Needle) = Ix => |
|||
Ix = find_last_of(Haystack,Needle), |
|||
if Ix < 0 then |
|||
throw $error(search_list_last(Needle),not_found) |
|||
end. |
|||
% Find all indices |
|||
search_list_all(Haystack,Needle) = Ixs => |
|||
Ixs = [Ix : {W,Ix} in zip(Haystack,1..Haystack.len), W == Needle], |
|||
if Ixs == [] then |
|||
throw $error(search_list_all(Needle),not_found) |
|||
end.</syntaxhighlight> |
|||
{{out}} |
|||
<pre>First 'Bush' = 5 |
|||
Last 'Bush' = 9 |
|||
All 'Bush' = [5,7,9] |
|||
error(search_list(Waldo),not_found) |
|||
Waldo = _3590</pre> |
|||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |
||
Note that in PicoLisp all indexes are one-based |
Note that in PicoLisp all indexes are one-based |
||
(the first element has the position '1') |
(the first element has the position '1') |
||
< |
<syntaxhighlight lang="picolisp">(de lastIndex (Item Lst) |
||
(- (length Lst) (index Item (reverse Lst)) -1) ) |
(- (length Lst) (index Item (reverse Lst)) -1) ) |
||
Line 1,500: | Line 3,249: | ||
(findNeedle index 'Washington Lst) |
(findNeedle index 'Washington Lst) |
||
(findNeedle index 'Bush Lst) |
(findNeedle index 'Bush Lst) |
||
(findNeedle lastIndex 'Bush Lst) )</ |
(findNeedle lastIndex 'Bush Lst) )</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<pre>Washington not found |
<pre>Washington not found |
||
Bush 5 |
Bush 5 |
||
Line 1,507: | Line 3,256: | ||
=={{header|PL/I}}== |
=={{header|PL/I}}== |
||
<syntaxhighlight lang="pli">search: procedure () returns (fixed binary); |
|||
<lang PL/I> |
|||
search: procedure () returns (fixed binary); |
|||
declare haystack (0:9) character (200) varying static initial |
declare haystack (0:9) character (200) varying static initial |
||
('apple', 'banana', 'celery', 'dumpling', 'egg', 'flour', |
('apple', 'banana', 'celery', 'dumpling', 'egg', 'flour', |
||
Line 1,528: | Line 3,276: | ||
signal condition(missing_needle); |
signal condition(missing_needle); |
||
return (lbound(haystack,1)-1); |
return (lbound(haystack,1)-1); |
||
end search; |
end search;</syntaxhighlight> |
||
</lang> |
|||
=={{header| |
=={{header|Plain English}}== |
||
<syntaxhighlight lang="plainenglish">To run: |
|||
{{works with|PowerBASIC for Windows}} |
|||
Start up. |
|||
Make an example haystack. |
|||
Find "b" in the example haystack giving a count. |
|||
Destroy the example haystack. |
|||
Write "The index of ""b"" is " then the count on the console. |
|||
Wait for the escape key. |
|||
Shut down. |
|||
A needle is a string. |
|||
<lang powerbasic>FUNCTION PBMAIN () AS LONG |
|||
DIM haystack(54) AS STRING |
|||
Some hay is some strings. |
|||
ARRAY ASSIGN haystack() = "foo", "bar", "baz", "quux", "quuux", "quuuux", _ |
|||
"bazola", "ztesch", "foo", "bar", "thud", "grunt", "foo", _ |
|||
A bale is a thing with some hay. |
|||
"bar", "bletch", "foo", "bar", "fum", "fred", "jim", _ |
|||
"sheila", "barney", "flarp", "zxc", "spqr", ";wombat", "shme", _ |
|||
A haystack is some bales. |
|||
"foo", "bar", "baz", "bongo", "spam", "eggs", "snork", "foo", _ |
|||
"bar", "zot", "blarg", "wibble", "toto", "titi", "tata", _ |
|||
To add some hay to a haystack: |
|||
"tutu", "pippo", "pluto", "paperino", "aap", "noot", "mies", _ |
|||
Allocate memory for a bale. |
|||
"oogle", "foogle", "boogle", "zork", "gork", "bork" |
|||
Put the hay into the bale's hay. |
|||
DIM needle AS STRING, found AS LONG, lastFound AS LONG |
|||
Append the bale to the haystack. |
|||
DO |
|||
needle = INPUTBOX$("Word to search for? (Leave blank to exit)") |
|||
To make an example haystack: |
|||
IF needle <> "" THEN |
|||
Add "a" to the example haystack. |
|||
' collate ucase -> case insensitive |
|||
Add "a" to the example haystack. |
|||
ARRAY SCAN haystack(), COLLATE UCASE, = needle, TO found |
|||
Add "b" to the example haystack. |
|||
IF found > 0 THEN |
|||
Add "c" to the example haystack. |
|||
lastFound = found |
|||
Add "d" to the example haystack. |
|||
MSGBOX "Found """ & needle & """ at index " & TRIM$(STR$(found - 1)) |
|||
IF found < UBOUND(haystack) THEN |
|||
\ As Plain English doesn't have exceptions, return -1 if the needle is not found. |
|||
DO |
|||
To find a needle in a haystack giving a count: |
|||
ARRAY SCAN haystack(lastFound), COLLATE UCASE, = needle, TO found |
|||
Get a bale from the haystack. |
|||
IF found > 0 THEN |
|||
Loop. |
|||
MSGBOX "Another occurence of """ & needle & """ at index " & _ |
|||
If the bale is nil, put -1 into the count; exit. |
|||
TRIM$(STR$(found + lastFound - 1)) |
|||
If the bale's hay is the needle, exit. |
|||
lastFound = found + lastFound |
|||
Put the bale's next into the bale. |
|||
ELSE |
|||
Bump the count. |
|||
MSGBOX "No more occurences of """ & needle & """ found" |
|||
Repeat.</syntaxhighlight> |
|||
EXIT DO 'will exit inner DO, not outer |
|||
{{out}} |
|||
END IF |
|||
<pre> |
|||
LOOP |
|||
The index of "b" is 2 |
|||
END IF |
|||
</pre> |
|||
ELSE |
|||
MSGBOX "No occurences of """ & needle & """ found" |
|||
=={{header|PowerShell}}== |
|||
END IF |
|||
{{works with|PowerShell|4.0}} |
|||
ELSE |
|||
<syntaxhighlight lang="powershell"> |
|||
EXIT DO |
|||
function index($haystack,$needle) { |
|||
END IF |
|||
$index = $haystack.IndexOf($needle) |
|||
LOOP |
|||
if($index -eq -1) { |
|||
END FUNCTION</lang> |
|||
Write-Warning "$needle is absent" |
|||
} else { |
|||
$index |
|||
} |
|||
} |
|||
$haystack = @("word", "phrase", "preface", "title", "house", "line", "chapter", "page", "book", "house") |
|||
index $haystack "house" |
|||
index $haystack "paragraph" |
|||
</syntaxhighlight> |
|||
<b>Output:</b> |
|||
<pre> |
|||
4 |
|||
WARNING: paragraph is absent |
|||
</pre> |
|||
===PowerShell Extra credit=== |
|||
The -Verbose switch is available to any advanced function. |
|||
<syntaxhighlight lang="powershell"> |
|||
function Find-Needle |
|||
{ |
|||
[CmdletBinding()] |
|||
[OutputType([int])] |
|||
Param |
|||
( |
|||
[Parameter(Mandatory=$true, Position=0)] |
|||
[string] |
|||
$Needle, |
|||
[Parameter(Mandatory=$true, Position=1)] |
|||
[string[]] |
|||
$Haystack, |
|||
[switch] |
|||
$LastIndex |
|||
) |
|||
if ($LastIndex) |
|||
{ |
|||
$index = [Array]::LastIndexOf($Haystack,$Needle) |
|||
if ($index -eq -1) |
|||
{ |
|||
Write-Verbose "Needle not found in Haystack" |
|||
return $index |
|||
} |
|||
if ((($Haystack | Group-Object | Where-Object Count -GT 1).Group).IndexOf($Needle) -ne -1) |
|||
{ |
|||
Write-Verbose "Last needle found in Haystack at index $index" |
|||
} |
|||
else |
|||
{ |
|||
Write-Verbose "Needle found in Haystack at index $index (No duplicates were found)" |
|||
} |
|||
return $index |
|||
} |
|||
else |
|||
{ |
|||
$index = [Array]::IndexOf($Haystack,$Needle) |
|||
if ($index -eq -1) |
|||
{ |
|||
Write-Verbose "Needle not found in Haystack" |
|||
} |
|||
else |
|||
{ |
|||
Write-Verbose "Needle found in Haystack at index $index" |
|||
} |
|||
return $index |
|||
} |
|||
} |
|||
$haystack = @("word", "phrase", "preface", "title", "house", "line", "chapter", "page", "book", "house") |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="powershell"> |
|||
Find-Needle "house" $haystack |
|||
</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> |
|||
4 |
|||
</pre> |
|||
<syntaxhighlight lang="powershell"> |
|||
Find-Needle "house" $haystack -Verbose |
|||
</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> |
|||
VERBOSE: Needle found in Haystack at index 4 |
|||
4 |
|||
</pre> |
|||
<syntaxhighlight lang="powershell"> |
|||
Find-Needle "house" $haystack -LastIndex -Verbose |
|||
</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> |
|||
VERBOSE: Last needle found in Haystack at index 9 |
|||
9 |
|||
</pre> |
|||
<syntaxhighlight lang="powershell"> |
|||
Find-Needle "title" $haystack -LastIndex -Verbose |
|||
</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> |
|||
VERBOSE: Needle found in Haystack at index 3 (No duplicates were found) |
|||
3 |
|||
</pre> |
|||
<syntaxhighlight lang="powershell"> |
|||
Find-Needle "something" $haystack -Verbose |
|||
</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> |
|||
VERBOSE: Needle not found in Haystack |
|||
-1 |
|||
</pre> |
|||
=={{header|Prolog}}== |
=={{header|Prolog}}== |
||
Works with SWI-Prolog |
Works with SWI-Prolog |
||
< |
<syntaxhighlight lang="prolog">search_a_list(N1, N2) :- |
||
L = ["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Boz", "Zag"], |
L = ["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Boz", "Zag"], |
||
Line 1,600: | Line 3,470: | ||
my_write(Name) :- |
my_write(Name) :- |
||
writef(' %s', [Name]). |
writef(' %s', [Name]). |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
|||
Output : |
|||
<pre> ?- search_a_list("Zag", "Simpson"). |
<pre> ?- search_a_list("Zag", "Simpson"). |
||
List is : Zig Zag Wally Ronald Bush Krusty Charlie Bush Boz Zag |
List is : Zig Zag Wally Ronald Bush Krusty Charlie Bush Boz Zag |
||
Line 1,611: | Line 3,481: | ||
true. |
true. |
||
</pre> |
</pre> |
||
=={{header|PureBasic}}== |
|||
<lang PureBasic>If OpenConsole() ; Open a simple console to interact with user |
|||
NewList Straws.s() |
|||
Define Straw$, target$="TBA" |
|||
Define found |
|||
Restore haystack ; Read in all the straws of the haystack. |
|||
Repeat |
|||
Read.s Straw$ |
|||
If Straw$<>"" |
|||
AddElement(Straws()) |
|||
Straws()=UCase(Straw$) |
|||
Continue |
|||
Else |
|||
Break |
|||
EndIf |
|||
ForEver |
|||
While target$<>"" |
|||
Print(#CRLF$+"Enter word to search for (leave blank to quit) :"): target$=Input() |
|||
ResetList(Straws()): found=#False |
|||
While NextElement(Straws()) |
|||
If UCase(target$)=Straws() |
|||
found=#True |
|||
PrintN(target$+" found as index #"+Str(ListIndex(Straws()))) |
|||
EndIf |
|||
Wend |
|||
If Not found |
|||
PrintN("Not found.") |
|||
EndIf |
|||
Wend |
|||
EndIf |
|||
DataSection |
|||
haystack: |
|||
Data.s "Zig","Zag","Zig","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo","" |
|||
EndDataSection</lang> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
||
< |
<syntaxhighlight lang="python">haystack=["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"] |
||
for needle in ("Washington","Bush"): |
for needle in ("Washington","Bush"): |
||
Line 1,657: | Line 3,489: | ||
print haystack.index(needle), needle |
print haystack.index(needle), needle |
||
except ValueError, value_error: |
except ValueError, value_error: |
||
print needle,"is not in haystack"</ |
print needle,"is not in haystack"</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
Washington is not in haystack |
Washington is not in haystack |
||
Line 1,664: | Line 3,496: | ||
</pre> |
</pre> |
||
Note that in Python, the index method of a list already raises an exception. |
Note that in Python, the index method of a list already raises an exception. |
||
The following shows the default information given |
|||
<lang python>>>> haystack=["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"] |
|||
when the exception is not captured in the program: |
|||
<syntaxhighlight lang="python">>>> haystack=["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"] |
|||
>>> haystack.index('Bush') |
>>> haystack.index('Bush') |
||
4 |
4 |
||
Line 1,673: | Line 3,507: | ||
haystack.index('Washington') |
haystack.index('Washington') |
||
ValueError: list.index(x): x not in list |
ValueError: list.index(x): x not in list |
||
>>></ |
>>></syntaxhighlight> |
||
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 [http://docs.python.org/library/stdtypes.html?highlight=rindex#str.rindex rindex]) |
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 [http://docs.python.org/library/stdtypes.html?highlight=rindex#str.rindex rindex]). |
||
Instead we need to look for the index in the reversed list and adjust the result. |
|||
<lang python>>>> def hi_index(needle, haystack): |
|||
<syntaxhighlight lang="python">>>> def hi_index(needle, haystack): |
|||
return len(haystack)-1 - haystack[::-1].index(needle) |
return len(haystack)-1 - haystack[::-1].index(needle) |
||
Line 1,687: | Line 3,522: | ||
assert hi == haystack.index(n), "index == hi_index if needle occurs only once" |
assert hi == haystack.index(n), "index == hi_index if needle occurs only once" |
||
>>></syntaxhighlight> |
|||
>>></lang> |
|||
=={{header|R}}== |
=={{header|R}}== |
||
< |
<syntaxhighlight lang="r">find.needle <- function(haystack, needle="needle", return.last.index.too=FALSE) |
||
{ |
{ |
||
indices <- which(haystack %in% needle) |
indices <- which(haystack %in% needle) |
||
if(length(indices)==0) stop("no needles in the haystack") |
if(length(indices)==0) stop("no needles in the haystack") |
||
if(return.last.index.too) range(indices) else min(indices) |
if(return.last.index.too) range(indices) else min(indices) |
||
}</ |
}</syntaxhighlight> |
||
Example usage: |
Example usage: |
||
< |
<syntaxhighlight lang="r">haystack1 <- c("where", "is", "the", "needle", "I", "wonder") |
||
haystack2 <- c("no", "sewing", "equipment", "in", "here") |
haystack2 <- c("no", "sewing", "equipment", "in", "here") |
||
haystack3 <- c("oodles", "of", "needles", "needles", "needles", "in", "here") |
haystack3 <- c("oodles", "of", "needles", "needles", "needles", "in", "here") |
||
Line 1,705: | Line 3,539: | ||
find.needle(haystack2) # error |
find.needle(haystack2) # error |
||
find.needle(haystack3) # 3 |
find.needle(haystack3) # 3 |
||
find.needle(haystack3, needle="needles", ret=TRUE) # 3 5</ |
find.needle(haystack3, needle="needles", ret=TRUE) # 3 5</syntaxhighlight> |
||
=={{header|Racket}}== |
|||
The function index returns the index of the the element x in the sequence xs. |
|||
If the element is not found, then #f is returned. |
|||
<syntaxhighlight lang="racket">(define (index xs y) |
|||
(for/first ([(x i) (in-indexed xs)] |
|||
#:when (equal? x y)) |
|||
i))</syntaxhighlight> |
|||
If the last index of an element is needed, for/last is used: |
|||
<syntaxhighlight lang="racket">(define (index-last xs y) |
|||
(for/last ([(x i) (in-indexed xs)] |
|||
#:when (equal? x y)) |
|||
i))</syntaxhighlight> |
|||
Both index and index-last can handle any sequence such as lists, vectors, sets etc. |
|||
Let us test with a linked list: |
|||
<syntaxhighlight lang="racket">(define haystack '("Zig" "Zag" "Wally" "Ronald" "Bush" "Krusty" "Charlie" "Bush" "Bozo")) |
|||
(for/list ([needle '("Bender" "Bush")]) |
|||
(index haystack needle)) |
|||
(for/list ([needle '("Bender" "Bush")]) |
|||
(index-last haystack needle))</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
'(#f 4) |
|||
'(#f 7) |
|||
</pre> |
|||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
{{works with|Rakudo Star|2016.07}} |
|||
<syntaxhighlight lang="raku" line>my @haystack = <Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo>; |
|||
for <Washington Bush> -> $needle { |
|||
say "$needle -- { @haystack.first($needle, :k) // 'not in haystack' }"; |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Washington -- not in haystack |
|||
Bush -- 4 |
|||
</pre> |
|||
<br> |
|||
Or, including the "extra credit" task: |
|||
{{works with|Rakudo Star|2016.07}} |
|||
<syntaxhighlight lang="raku" line>my Str @haystack = <Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo>; |
|||
for <Washingston Bush> -> $needle { |
|||
my $first = @haystack.first($needle, :k); |
|||
if defined $first { |
|||
my $last = @haystack.first($needle, :k, :end); |
|||
say "$needle -- first at $first, last at $last"; |
|||
} |
|||
else { |
|||
say "$needle -- not in haystack"; |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Washingston -- not in haystack |
|||
Bush -- first at 4, last at 7 |
|||
</pre> |
|||
The built-in method <code>.first</code> takes a [https://docs.raku.org/language/operators#infix_~~ smart-matcher], and returns the first matching list element.<br> |
|||
The <code>:k</code> adverb tells it to return the key (a.k.a. list index) instead of the value of the matching element.<br> |
|||
The <code>:end</code> adverb tells it to start searching from the end of the list.<br> |
|||
<br> |
|||
If you plan to do many searches on the same large list, you might want to build a search hash first for efficient look-up: |
|||
<syntaxhighlight lang="raku" line>my @haystack = <Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo>; |
|||
my %index; |
|||
%index{.value} //= .key for @haystack.pairs; |
|||
for <Washington Bush> -> $needle { |
|||
say "$needle -- { %index{$needle} // 'not in haystack' }"; |
|||
}</syntaxhighlight> |
|||
=={{header|REBOL}}== |
=={{header|REBOL}}== |
||
< |
<syntaxhighlight lang="rebol">REBOL [ |
||
Title: "List Indexing" |
Title: "List Indexing" |
||
Author: oofoe |
|||
Date: 2009-12-06 |
|||
URL: http://rosettacode.org/wiki/Index_in_a_list |
URL: http://rosettacode.org/wiki/Index_in_a_list |
||
] |
] |
||
Line 1,747: | Line 3,662: | ||
reform [needle "=>" locate/largest haystack needle] |
reform [needle "=>" locate/largest haystack needle] |
||
] |
] |
||
]</ |
]</syntaxhighlight> |
||
Output: |
|||
{{out}} |
|||
<pre>Search for first occurance: |
<pre>Search for first occurance: |
||
Washington is not in haystack. |
Washington is not in haystack. |
||
Line 1,760: | Line 3,674: | ||
=={{header|REXX}}== |
=={{header|REXX}}== |
||
===version 1=== |
|||
This REXX program searches a collection of string (haystack) that are |
|||
This REXX program searches a collection of string (haystack) |
|||
stored in a sequential REXX array. |
|||
that are stored in a sequential REXX array. |
|||
<br><br> |
|||
No counter is kept of the number of |
<br><br>No counter is kept of the number of items, |
||
but they should be numbered consecutively and can't have any gaps. |
|||
<br><br>The haystack items may have any character, including blanks. |
|||
<br><br> |
|||
<br>A ''null'' value isn't allowed in this method of representing values. |
|||
The haystack items may have any character, including blanks. A null |
|||
<syntaxhighlight lang="rexx">/*REXX program searches a collection of strings (an array of periodic table elements).*/ |
|||
value isn't allowed. |
|||
hay.= /*initialize the haystack collection. */ |
|||
<lang rexx> |
|||
hay.1 = 'sodium' |
|||
/*REXX program searches a collection of strings, version 1. */ |
|||
hay.2 = 'phosphorous' |
|||
hay.3 = 'californium' |
|||
hay.4 = 'copernicium' |
|||
hay.5 = 'gold' |
|||
hay.6 = 'thallium' |
|||
hay.7 = 'carbon' |
|||
hay.8 = 'silver' |
|||
hay.9 = 'curium' |
|||
hay.10 = 'copper' |
|||
hay.11 = 'helium' |
|||
hay.12 = 'sulfur' |
|||
needle = 'gold' /*we'll be looking for the gold. */ |
|||
upper needle /*in case some people capitalize stuff.*/ |
|||
hay.1 ='sodium' |
|||
found=0 /*assume the needle isn't found yet. */ |
|||
hay.2 ='phosphorous' |
|||
hay.3 ='califonium' |
|||
hay.4 ='copernicium' |
|||
hay.5 ='gold' |
|||
hay.6 ='thallium' |
|||
hay.7 ='carbon' |
|||
hay.8 ='silver' |
|||
hay.9 ='curium' |
|||
hay.10='copper' |
|||
hay.11='helium' |
|||
hay.12='sulfur' |
|||
do j=1 while hay.j\=='' /*keep looking in the haystack. */ |
|||
_=hay.j; upper _ /*make it uppercase to be safe. */ |
|||
if _=needle then do; found=1 /*we've found the needle in haystack. */ |
|||
leave /* ··· and stop looking, of course. */ |
|||
end |
|||
end /*j*/ |
|||
if found then return j /*return the haystack index number. */ |
|||
else say needle "wasn't found in the haystack!" |
|||
return 0 /*indicates the needle wasn't found. */</syntaxhighlight> |
|||
===version 2=== |
|||
This REXX program searches a collection of string (haystack) |
|||
do j=1 while hay.j\=='' /*keep looking in haystack until nul. */ |
|||
that are stored in a REXX array (which may have gaps). |
|||
if hay.j=needle then do /*we've found a needle in the haystack.*/ |
|||
<br><br>A safe counter is kept of the maximum (highest) index in the array, |
|||
found=1 /*indicate that a needle was found.*/ |
|||
leave /* and stop looking, of course.*/ |
|||
end |
|||
end |
|||
if \found then say needle "wasn't found in the haystack!" |
|||
</lang> |
|||
This REXX program searches a collection of string (haystack) that are |
|||
stored in a REXX array (which may have gaps). |
|||
<br><br> |
|||
A safe counter is kept of the maximum (highest) index in the array, |
|||
this counter may be any sufficiently high number. |
this counter may be any sufficiently high number. |
||
<br><br>The array may be out of order (but not recommended!). |
|||
<br><br> |
|||
<syntaxhighlight lang="rexx">/*REXX program searches a collection of strings (an array of periodic table elements).*/ |
|||
The array may be out of order (but not recommended!). |
|||
hay.0 = 1000 /*safely indicate highest item number. */ |
|||
<lang rexx> |
|||
hay.200 = 'Binilnilium' |
|||
/*REXX program searches a collection of strings, version 2. */ |
|||
hay.98 = 'californium' |
|||
hay.6 = 'carbon' |
|||
hay.112 = 'copernicium' |
|||
hay.29 = 'copper' |
|||
hay.114 = 'flerovium' |
|||
hay.79 = 'gold' |
|||
hay.2 = 'helium' |
|||
hay.1 = 'hydrogen' |
|||
hay.82 = 'lead' |
|||
hay.116 = 'livermorium' |
|||
hay.15 = 'phosphorous' |
|||
hay.47 = 'silver' |
|||
hay.11 = 'sodium' |
|||
hay.16 = 'sulfur' |
|||
hay.81 = 'thallium' |
|||
hay.92 = 'uranium' |
|||
/* [↑] sorted by the element name. */ |
|||
needle = 'gold' /*we'll be looking for the gold. */ |
|||
upper needle /*in case some people capitalize. */ |
|||
found=0 /*assume the needle isn't found (yet).*/ |
|||
hay.0 |
do j=1 for hay.0 /*start looking in haystack, item 1. */ |
||
_=hay.j; upper _ /*make it uppercase just to be safe. */ |
|||
hay.1 ='sodium' |
|||
if _=needle then do; found=1 /*we've found the needle in haystack. */ |
|||
hay.2 ='phosphorous' |
|||
leave /* ··· and stop looking, of course. */ |
|||
hay.3 ='califonium' |
|||
end |
|||
hay.7 ='copernicium' |
|||
end /*j*/ |
|||
hay.9 ='gold' |
|||
hay.16='thallium' |
|||
hay.27='carbon' |
|||
hay.30='silver' |
|||
hay.33='lead' |
|||
hay.45='copper' |
|||
hay.46='helium' |
|||
hay.10='sulfur' |
|||
if found then return j /*return the haystack index number. */ |
|||
else say needle "wasn't found in the haystack!" |
|||
return 0 /*indicates the needle wasn't found. */</syntaxhighlight> |
|||
===version 3=== |
|||
needle='gold' /*we'll be looking for the gold. */ |
|||
This REXX program searches a collection of string (haystack) |
|||
found=0 /*assume needle isn't found (so far). */ |
|||
that are stored in a REXX array. |
|||
<br><br>This form uses a type of array called a '''sparse array''' (with non-numeric indexes). |
|||
<br><br>One drawback of this approach is that the items can't have leading/trailing/imbedded blanks, |
|||
<br>nor can they have special characters. |
|||
<br><br>Only letters, numerals, and a few special characters are allowed: '''!''', '''@''', '''#''', '''$''', '''?''', and '''_'''. |
|||
<br><br>This method (finding a needle in a haystack) is extremely fast as there isn't any |
|||
<br>table look-up, the "finding" is done by REXX's own internal method of variable lookup, |
|||
<br>and, for the most part, it based on a table hashing algorithm. |
|||
<br><br>This method pre-prends an underscore (underbar) to avoid collision with any REXX |
|||
<br>variable names. Therefore, there shouldn't be any REXX variable names (in this |
|||
<br>program) that have a leading underscore ('''_'''). |
|||
<syntaxhighlight lang="rexx">/*REXX program searches a collection of strings (an array of periodic table elements).*/ |
|||
hay.=0 /*initialize the haystack collection. */ |
|||
hay._sodium = 1 |
|||
hay._phosphorous = 1 |
|||
hay._californium = 1 |
|||
hay._copernicium = 1 |
|||
hay._gold = 1 |
|||
hay._thallium = 1 |
|||
hay._carbon = 1 |
|||
hay._silver = 1 |
|||
hay._copper = 1 |
|||
hay._helium = 1 |
|||
hay._sulfur = 1 |
|||
/*underscores (_) are used to NOT ... */ |
|||
/* ... conflict with variable names. */ |
|||
needle = 'gold' /*we'll be looking for the gold. */ |
|||
if hay.j=needle then do /*we've found a needle in the haystack.*/ |
|||
found=1 /*indicate that a needle was found.*/ |
|||
leave /* and stop looking, of course.*/ |
|||
end |
|||
end |
|||
Xneedle = '_'needle /*prefix an underscore (_) character. */ |
|||
if \found then say needle "wasn't found in the haystack!" |
|||
upper Xneedle /*uppercase: how REXX stores them. */ |
|||
/*alternative version of above: */ |
|||
/* Xneedle=translate('_'needle) */ |
|||
hayItems=0 |
|||
found=hay.Xneedle /*this is it, it's found (or maybe not)*/ |
|||
if hay.k\=='' then hayItems=hayItems+1 /*bump the item counter.*/ |
|||
end |
|||
</lang> |
|||
This REXX program searches a collection of string (haystack) that are |
|||
stored in a REXX array. |
|||
<br><br> |
|||
This form uses a type of array called a |
|||
sparse arrow (with non-numeric indexes). |
|||
<br><br> |
|||
One drawback of this approach |
|||
is that the items can't have leading/trailing/imbedded blanks, nor can |
|||
they have special characters. |
|||
<br><br> |
|||
Only letters, numerals, and a few special |
|||
characters are allowed: !, @, #, $, ?, and _. |
|||
<br><br> |
|||
This method (finding a needle in a haystack) is extremely fast as there |
|||
isn't any table lookup, the "finding" is done by REXX's own internal |
|||
method of variable lookup, and, for the most part, it based on a table |
|||
hashing algorithm. |
|||
<br><br> |
|||
This method pre-prends an underscore (underbar) to avoid collision with |
|||
any REXX variable names. Therefore, there shouldn't be any REXX variable |
|||
names (in this program) that have a leading underscore (_). |
|||
<lang rexx> |
|||
/*REXX program searches a collection of strings, version 3. */ |
|||
if found then return j /*return the haystack index number. */ |
|||
else say needle "wasn't found in the haystack!" |
|||
hay._sodium =1 |
|||
return 0 /*indicates the needle wasn't found. */</syntaxhighlight> |
|||
hay._phosphorous =1 |
|||
hay._califonium =1 |
|||
hay._copernicium =1 |
|||
hay._gold =1 |
|||
hay._thallium =1 |
|||
hay._carbon =1 |
|||
hay._silver =1 |
|||
hay._copper =1 |
|||
hay._helium =1 |
|||
hay._sulfur =1 |
|||
===version 4=== |
|||
This method uses a simple string (so haystack items can't have embedded blanks or tabs in them). |
|||
<br>Code was added to uppercase both the '''haystack''' and the '''needle''' to make the search ''case insensitive''. |
|||
<syntaxhighlight lang="rexx">/*REXX program searches a collection of strings (an array of periodic table elements).*/ |
|||
/*───────────────names of the first 200 elements of the periodic table.─────────────*/ |
|||
_= 'hydrogen helium lithium beryllium boron carbon nitrogen oxygen fluorine neon sodium' |
|||
_=_ 'magnesium aluminum silicon phosphorous sulfur chlorine argon potassium calcium' |
|||
_=_ 'scandium titanium vanadium chromium manganese iron cobalt nickel copper zinc' |
|||
_=_ 'gallium germanium arsenic selenium bromine krypton rubidium strontium yttrium' |
|||
_=_ 'zirconium niobium molybdenum technetium ruthenium rhodium palladium silver cadmium' |
|||
_=_ 'indium tin antimony tellurium iodine xenon cesium barium lanthanum cerium' |
|||
_=_ 'praseodymium neodymium promethium samarium europium gadolinium terbium dysprosium' |
|||
_=_ 'holmium erbium thulium ytterbium lutetium hafnium tantalum tungsten rhenium osmium' |
|||
_=_ 'iridium platinum gold mercury thallium lead bismuth polonium astatine radon' |
|||
_=_ 'francium radium actinium thorium protactinium uranium neptunium plutonium americium' |
|||
_=_ 'curium berkelium californium einsteinium fermium mendelevium nobelium lawrencium' |
|||
_=_ 'rutherfordium dubnium seaborgium bohrium hassium meitnerium darmstadtium' |
|||
_=_ 'roentgenium copernicium nihonium flerovium moscovium livermorium tennessine' |
|||
_=_ 'oganesson ununennium unbinilium unbiunium unbibium unbitrium unbiquadium' |
|||
_=_ 'unbipentium unbihexium unbiseptium unbioctium unbiennium untrinilium untriunium' |
|||
_=_ 'untribium untritrium untriquadium untripentium untrihexium untriseptium untrioctium' |
|||
_=_ 'untriennium unquadnilium unquadunium unquadbium unquadtrium unquadquadium' |
|||
_=_ 'unquadpentium unquadhexium unquadseptium unquadoctium unquadennium unpentnilium' |
|||
_=_ 'unpentunium unpentbium unpenttrium unpentquadium unpentpentium unpenthexium' |
|||
_=_ 'unpentseptium unpentoctium unpentennium unhexnilium unhexunium unhexbium unhextrium' |
|||
_=_ 'unhexquadium unhexpentium unhexhexium unhexseptium unhexoctium unhexennium' |
|||
_=_ 'unseptnilium unseptunium unseptbium unsepttrium unseptquadium unseptpentium' |
|||
_=_ 'unsepthexium unseptseptium unseptoctium unseptennium unoctnilium unoctunium' |
|||
_=_ 'unoctbium unocttrium unoctquadium unoctpentium unocthexium unoctseptium unoctoctium' |
|||
_=_ 'unoctennium unennilium unennunium unennbium unenntrium unennquadium unennpentium' |
|||
_=_ 'unennhexium unennseptium unennoctium unennennium binilnilium' |
|||
haystack= _ /*assign the elements ───► haystack. */ |
|||
needle = 'gold' /*we'll be looking for the gold. */ |
|||
upper |
upper needle haystack /*in case some people capitalize stuff.*/ |
||
idx= wordpos(needle, haystack) /*use REXX's BIF: WORDPOS */ |
|||
if idx\==0 then return idx /*return the haystack index number. */ |
|||
else say needle "wasn't found in the haystack!" |
|||
return 0 /*indicates the needle wasn't found. */ |
|||
/*stick a fork in it, we're all done. */</syntaxhighlight> |
|||
=={{header|Ring}}== |
|||
found=hay.Xneedle /*this is it, it's found or it ain't. */ |
|||
<syntaxhighlight lang="ring"> |
|||
haystack = ["alpha","bravo","charlie","delta","echo","foxtrot","golf", |
|||
"hotel","india","juliet","kilo","lima","mike","needle", |
|||
"november","oscar","papa","quebec","romeo","sierra","tango", |
|||
"needle","uniform","victor","whisky","x-ray","yankee","zulu"] |
|||
needle = "needle" |
|||
if \found then say needle "wasn't found in the haystack!" |
|||
maxindex = len(haystack) |
|||
</lang> |
|||
This REXX program searches a collection of string (haystack) that are |
|||
for index = 1 to maxindex |
|||
stored in a sequential REXX array (as in version 2). |
|||
if needle = haystack[index] exit ok |
|||
<br><br> |
|||
next |
|||
This version finds the LAST occurance of the needle. |
|||
if index <= maxindex |
|||
<lang rexx> |
|||
see "first found at index " + index + nl ok |
|||
/*REXX program searches a collection of strings, version 4. */ |
|||
for last = maxindex to 0 step -1 |
|||
if needle = haystack[last] exit ok |
|||
hay.0=100 /*safely indicate the highest item num.*/ |
|||
next |
|||
hay.1 ='sodium' |
|||
if !=index see " last found at index " + last + nl |
|||
hay.2 ='phosphorous' |
|||
else see "not found" + nl ok |
|||
hay.3 ='califonium' |
|||
</syntaxhighlight> |
|||
hay.7 ='copernicium' |
|||
Output: |
|||
hay.9 ='gold' |
|||
<pre> |
|||
hay.16='thallium' |
|||
first found at index : 14 |
|||
hay.27='carbon' |
|||
last found at index : 22 |
|||
hay.30='silver' |
|||
</pre> |
|||
hay.31='gold' |
|||
hay.45='copper' |
|||
hay.46='helium' |
|||
hay.10='sulfur' |
|||
=={{header|RPL}}== |
|||
{{works with|HP|48G}} |
|||
{ "Zig" "Zag" "Zig" "Wally" "Ronald" "Bush" "Krusty" "Charlie" "Bush" "Bozo" } '<span style="color:green">HAYSTACK</span>' STO |
|||
≪ → up |
|||
≪ <span style="color:green">HAYSTACK</span> |
|||
'''IF''' up NOT '''THEN''' REVLIST '''END''' |
|||
'''IF''' SWAP POS '''THEN''' |
|||
LASTARG |
|||
'''ELSE ''' |
|||
"LOOKHAY Error: |
|||
Needle not found" DOERR |
|||
'''END''' |
|||
≫ ≫ '<span style="color:blue">LOOKHAY</span>' STO |
|||
"Bush" 1 <span style="color:blue">LOOKHAY</span> |
|||
needle='gold' /*we'll be looking for the gold. */ |
|||
"Bush" 0 <span style="color:blue">LOOKHAY</span> |
|||
found=0 /*assume needle isn't found (so far). */ |
|||
{{out}} |
|||
<pre> |
|||
do j=1 for hay.0 /*start looking in the haystack, item 1*/ |
|||
2: 6 |
|||
if hay.j=needle then found=1 /*we've found a needle in haystack.*/ |
|||
1: 2 |
|||
end /*(above) will find last occurance.*/ |
|||
</pre> |
|||
if \found then say needle "wasn't found in the haystack!" |
|||
</lang> |
|||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
< |
<syntaxhighlight lang="ruby">haystack = %w(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo) |
||
%w(Bush Washington).each do |needle| |
%w(Bush Washington).each do |needle| |
||
if (i = haystack.index(needle)) |
if (i = haystack.index(needle)) |
||
puts "#{i} #{needle}" |
|||
else |
else |
||
raise "#{needle} is not in haystack\n" |
raise "#{needle} is not in haystack\n" |
||
end |
end |
||
end</ |
end</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
4 Bush |
4 Bush |
||
Line 1,940: | Line 3,903: | ||
from search_a_list.rb:4:in `<main>' |
from search_a_list.rb:4:in `<main>' |
||
</pre> |
</pre> |
||
'''extra credit''' |
|||
'''Extra credit''' |
|||
<lang ruby>haystack.each do |item| |
|||
<syntaxhighlight lang="ruby">haystack.each do |item| |
|||
last = haystack.rindex(item) |
last = haystack.rindex(item) |
||
if last > haystack.index(item) |
if last > haystack.index(item) |
||
Line 1,947: | Line 3,911: | ||
break |
break |
||
end |
end |
||
end |
end |
||
#=> Bush last appears at index 7</syntaxhighlight> |
|||
or, {{works with|Ruby|1.8.7}} |
|||
or |
|||
<lang ruby>multi_item = haystack .each_with_index .group_by {|elem, idx| elem} .find {|key, val| val.length > 1} |
|||
<syntaxhighlight lang="ruby">multi_item = haystack.each_index.group_by{|idx| haystack[idx]}.select{|key, val| val.length > 1} |
|||
# multi_item is => ["Bush", [["Bush", 4], ["Bush", 7]]] |
|||
# multi_item is => {"Bush"=>[4, 7]} |
|||
puts "#{multi_item[0]} last appears at index #{multi_item[1][-1][1]}" unless multi_item.nil?</lang> |
|||
multi_item.each do |key, val| |
|||
puts "#{key} appears at index #{val}" |
|||
end |
|||
#=> Bush appears at index [4, 7]</syntaxhighlight> |
|||
=={{header|Rust}}== |
|||
Rust encourages to encode possible errors in function's return type. For example, <code>position</code> returns <code>Option<usize></code>, which can be <code>None</code> or <code>Some(x)</code>. |
|||
<syntaxhighlight lang="rust">fn main() { |
|||
=={{header|Run BASIC}}== |
|||
let haystack=vec!["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", |
|||
"Bush", "Boz", "Zag"]; |
|||
needle$ = "Zag Wally Bush Chicken" |
|||
println!("First occurence of 'Bush' at {:?}",haystack.iter().position(|s| *s=="Bush")); |
|||
while word$(needle$,i+1," ") <> "" |
|||
println!("Last occurence of 'Bush' at {:?}",haystack.iter().rposition(|s| *s=="Bush")); |
|||
i = i + 1 |
|||
println!("First occurence of 'Rob' at {:?}",haystack.iter().position(|s| *s=="Rob")); |
|||
thisNeedle$ = word$(needle$,i," ") + " " |
|||
} |
|||
j = instr(haystack$,thisNeedle$) |
|||
</syntaxhighlight> |
|||
k1 = 0 |
|||
k = instr(haystack$,thisNeedle$,j+1) |
|||
{{out}} |
|||
while k <> 0 |
|||
k1 = k |
|||
<pre>First occurence of 'Bush' at Some(4) |
|||
k = instr(haystack$,thisNeedle$,k+1) |
|||
Last occurence of 'Bush' at Some(7) |
|||
wend |
|||
First occurence of 'Rob' at None |
|||
if j <> 0 then |
|||
</pre> |
|||
print thisNeedle$;" located at:";j; |
|||
if k1 <> 0 then print " Last position located at:";k1; |
|||
===Version that panics=== |
|||
print |
|||
else |
|||
<syntaxhighlight lang="rust">fn main() { |
|||
print thisNeedle$;" is not in the list" |
|||
let haystack=vec!["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", |
|||
end if |
|||
"Bush", "Boz", "Zag"]; |
|||
wend</lang>Output: |
|||
<pre>Zag located at:5 |
|||
println!("First occurence of 'Bush' at {:?}",haystack.iter().position(|s| *s=="Bush").unwrap()); |
|||
Wally located at:9 |
|||
println!("Last occurence of 'Bush' at {:?}",haystack.iter().rposition(|s| *s=="Bush").unwrap()); |
|||
Bush located at:22 Last position located at:52 |
|||
println!("First occurence of 'Rob' at {:?}",haystack.iter().position(|s| *s=="Rob").unwrap()); |
|||
Chicken is not in the list</pre> |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre>First occurence of 'Bush' at 4 |
|||
Last occurence of 'Bush' at 7 |
|||
thread '<main>' panicked at 'called `Option::unwrap()` on a `None` value', /home/rustbuild/src/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libcore/option.rs:362 |
|||
playpen: application terminated with error code 101 |
|||
</pre> |
|||
=={{header|S-lang}}== |
|||
<syntaxhighlight lang="s-lang">variable haystack = ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo","Ronald"]; |
|||
define find(needle) |
|||
{ |
|||
variable i = where(haystack == needle); |
|||
if (length(i)) { |
|||
% print(sprintf("%s: first=%d, last=%d", needle, i[0], i[-1])); |
|||
return(i[0], i[-1]); |
|||
} |
|||
else |
|||
throw ApplicationError, "an exception"; |
|||
} |
|||
($1, $2) = find("Ronald"); % returns 3, 9 |
|||
($1, $2) = find("McDonald"); % throws ApplicationError, labelled "an exception" |
|||
</syntaxhighlight> |
|||
=={{header|Sather}}== |
=={{header|Sather}}== |
||
{{trans|C_sharp}} |
{{trans|C_sharp}} |
||
< |
<syntaxhighlight lang="sather">class MAIN is |
||
main is |
main is |
||
haystack :ARRAY{STR} := |"Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Bozo"|; |
haystack :ARRAY{STR} := |"Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Bozo"|; |
||
Line 1,997: | Line 3,995: | ||
end; |
end; |
||
end; |
end; |
||
end;</syntaxhighlight> |
|||
end; |
|||
</lang> |
|||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
The method indexOf, defined for all classes inheriting from, |
The method indexOf, defined for all classes inheriting from, |
||
or having an implicit conversion to, |
|||
Seq returns the index of the first element, or -1 if none exists. The method lastIndexOf does the |
|||
Seq returns the index of the first element, or -1 if none exists. |
|||
same for the last element. Neither throws an exception, but that's easily done afterwards. |
|||
The method lastIndexOf does the same for the last element. |
|||
Neither throws an exception, but that's easily done afterwards. |
|||
However, a simple implementation, |
However, a simple implementation, |
||
not using those or similar methods might be written like this: |
|||
< |
<syntaxhighlight lang="scala">def findNeedles(needle: String, haystack: Seq[String]) = haystack.zipWithIndex.filter(_._1 == needle).map(_._2) |
||
def firstNeedle(needle: String, haystack: Seq[String]) = findNeedles(needle, haystack).head |
def firstNeedle(needle: String, haystack: Seq[String]) = findNeedles(needle, haystack).head |
||
def lastNeedle(needle: String, haystack: Seq[String]) = findNeedles(needle, haystack).last</ |
def lastNeedle(needle: String, haystack: Seq[String]) = findNeedles(needle, haystack).last</syntaxhighlight> |
||
It does raise an exception if there's no needle. |
It does raise an exception if there's no needle. |
||
=={{header|Scheme}}== |
=={{header|Scheme}}== |
||
<syntaxhighlight lang="scheme">(define haystack |
|||
<lang scheme> |
|||
(define haystack |
|||
'("Zig" "Zag" "Wally" "Ronald" "Bush" "Krusty" "Charlie" "Bush" "Bozo")) |
'("Zig" "Zag" "Wally" "Ronald" "Bush" "Krusty" "Charlie" "Bush" "Bozo")) |
||
Line 2,030: | Line 4,029: | ||
(if tail |
(if tail |
||
(- (length tail) 1) |
(- (length tail) 1) |
||
(throw 'needle-missing))))) |
(throw 'needle-missing)))))</syntaxhighlight> |
||
{{out}} |
|||
</lang> |
|||
<pre> |
<pre> |
||
(index-of "Bush" haystack) |
(index-of "Bush" haystack) |
||
4 |
4 |
||
(last-index-of "Bush" haystack) |
(last-index-of "Bush" haystack) |
||
7 |
|||
</pre> |
|||
=={{header|SenseTalk}}== |
|||
<syntaxhighlight lang="sensetalk"> |
|||
put ("apple", "banana", "cranberry" ,"durian", "eggplant", "grape", "banana", "appl", "blackberry") into fruitList |
|||
put findInList(fruitList,"banana") // 2 |
|||
put findInList(fruitList,"banana", true) // 7 |
|||
put findInList(fruitList,"tomato") // throws an exception |
|||
function findInList paramList, paramItem, findLast |
|||
set temp to every offset of paramItem within paramList |
|||
if (number of items in temp = 0) |
|||
Throw InvalidSearch, "Item not found in list" |
|||
end if |
|||
if findLast |
|||
return last item of temp |
|||
else |
|||
return first item of temp |
|||
end if |
|||
end findInList |
|||
</syntaxhighlight> |
|||
Note: Sensetalk indexes from 1 |
|||
=={{header|Sidef}}== |
|||
<syntaxhighlight lang="ruby">var haystack = %w(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo); |
|||
%w(Bush Washington).each { |needle| |
|||
var i = haystack.first_index{|item| item == needle}; |
|||
if (i >= 0) { |
|||
say "#{i} #{needle}"; |
|||
} else { |
|||
die "#{needle} is not in haystack"; |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
4 Bush |
|||
Washington is not in haystack at find.sf line 9. |
|||
</pre> |
|||
Extra credit: |
|||
<syntaxhighlight lang="ruby">var haystack = %w(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo); |
|||
say haystack.last_index{|item| item == "Bush"};</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
7 |
7 |
||
</pre> |
</pre> |
||
=={{header|Slate}}== |
=={{header|Slate}}== |
||
< |
<syntaxhighlight lang="slate">define: #haystack -> ('Zig,Zag,Wally,Ronald,Bush,Krusty,Charlie,Bush,Bozo' splitWith: $,). |
||
{'Washington'. 'Bush'} do: [| :needle | |
{'Washington'. 'Bush'} do: [| :needle | |
||
(haystack indexOf: needle) |
(haystack indexOf: needle) |
||
Line 2,049: | Line 4,093: | ||
lastIndex: (haystack lastIndexOf: word). |
lastIndex: (haystack lastIndexOf: word). |
||
lastIndex isNotNil /\ (lastIndex > firstIndex) ifTrue: |
lastIndex isNotNil /\ (lastIndex > firstIndex) ifTrue: |
||
[inform: 'last occurrence of ' ; word ; ' is at index ' ; lastIndex]]].</ |
[inform: 'last occurrence of ' ; word ; ' is at index ' ; lastIndex]]].</syntaxhighlight> |
||
=={{header|Smalltalk}}== |
=={{header|Smalltalk}}== |
||
{{works with|GNU Smalltalk}} |
{{works with|GNU Smalltalk}}{{works with|Smalltalk/X}} |
||
Smalltalk indexes start at 1. |
Notice: Smalltalk indexes start at 1. |
||
< |
<syntaxhighlight lang="smalltalk">| haystack | |
||
haystack := 'Zig,Zag,Wally,Ronald,Bush,Krusty,Charlie,Bush,Bozo' subStrings: $,. |
|||
haystack := |
|||
{ 'Washington' . 'Bush' } do: [:word | |
|||
'Zig,Zag,Wally,Ronald,Bush,Krusty,Charlie,Bush,Bozo' subStrings: $,. |
|||
|t| |
|||
{ 'Washington' . 'Bush' } do: [:i| |
|||
t := |
((t := haystack indexOf: word) = 0) |
||
ifTrue: [ ('%1 is not in the haystack' % { word }) displayNl ] |
|||
ifFalse: [ |
ifFalse: [ |
||
|l| |
|||
l := ( (haystack size) - (haystack reverse indexOf: i) + 1 ). |
|||
('%1 is at index %2' % { word . t }) displayNl. |
|||
l := ( (haystack size) - (haystack reverse indexOf: word) + 1 ). |
|||
( t = l ) ifFalse: [ |
|||
] |
('last occurence of %1 is at index %2' % { word . l }) displayNl ] |
||
] |
|||
].</lang> |
|||
].</syntaxhighlight> |
|||
the above example did not raise an exception; the following does (a handler has been added to proceed for more search words): |
|||
{{works with|Smalltalk/X}} |
|||
Notice: the code below uses the ST/X embedded-expression-string extension. |
|||
<syntaxhighlight lang="smalltalk">| haystack | |
|||
haystack := 'Zig,Zag,Wally,Ronald,Bush,Krusty,Charlie,Bush,Bozo' subStrings: $,. |
|||
[ |
|||
{ 'Washington' . 'Bush' . 'Ronald' } do: [:word | |
|||
|firstIdx lastIdx| |
|||
firstIdx := haystack |
|||
indexOf:word |
|||
ifAbsent:[ |
|||
ProceedableError raiseRequestWith:word errorString:'not found'. |
|||
0 |
|||
]. |
|||
firstIdx = 0 ifFalse:[ |
|||
(lastIdx := haystack lastIndexOf:word) = firstIdx |
|||
ifTrue:[ e'the first index of {word} is {firstIdx}' printCR ] |
|||
ifFalse:[ e'the last index of {word} is {lastIdx}' printCR ]] |
|||
] |
|||
] on:Error do:[:ex | |
|||
e'{ex description} exception raised for: {ex parameter}' printCR. |
|||
'but I don''t care and proceed...' printCR. |
|||
ex proceed. |
|||
]</syntaxhighlight> |
|||
{{out}} |
|||
<pre>not found exception raised for: Washington |
|||
but I don't care and proceed... |
|||
the last index of Bush is 8 |
|||
the first index of Ronald is 4</pre> |
|||
=={{header|Standard ML}}== |
=={{header|Standard ML}}== |
||
< |
<syntaxhighlight lang="sml">fun find_index (pred, lst) = let |
||
fun loop (n, []) = NONE |
fun loop (n, []) = NONE |
||
| loop (n, x::xs) = if pred x then SOME n |
| loop (n, x::xs) = if pred x then SOME n |
||
Line 2,085: | Line 4,160: | ||
SOME i => print (Int.toString i ^ " " ^ needle ^ "\n") |
SOME i => print (Int.toString i ^ " " ^ needle ^ "\n") |
||
| NONE => print (needle ^ " is not in haystack\n")) |
| NONE => print (needle ^ " is not in haystack\n")) |
||
["Washington", "Bush"];</ |
["Washington", "Bush"];</syntaxhighlight> |
||
=={{header|Swift}}== |
|||
{{works with|Swift|2.x+}} |
|||
<syntaxhighlight lang="swift">let haystack = ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"] |
|||
for needle in ["Washington","Bush"] { |
|||
if let index = haystack.indexOf(needle) { |
|||
print("\(index) \(needle)") |
|||
} else { |
|||
print("\(needle) is not in haystack") |
|||
} |
|||
}</syntaxhighlight> |
|||
{{works with|Swift|1.x}} |
|||
<syntaxhighlight lang="swift">let haystack = ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"] |
|||
for needle in ["Washington","Bush"] { |
|||
if let index = find(haystack, needle) { |
|||
println("\(index) \(needle)") |
|||
} else { |
|||
println("\(needle) is not in haystack") |
|||
} |
|||
}</syntaxhighlight> |
|||
The second task: |
|||
{{works with|Swift|2.x+}} |
|||
<syntaxhighlight lang="swift"> |
|||
// the second part can be done several ways, but extending any Array of Comparable objects is the most generic approach |
|||
extension Array where Element : Comparable { |
|||
func lastIndexMatching(needle:Element) -> Int? { |
|||
for i in stride(from: count-1, through: 0, by: -1) { |
|||
if self[i] == needle { |
|||
return i |
|||
} |
|||
} |
|||
return nil |
|||
} |
|||
} |
|||
for needle in ["Washington","Bush"] { |
|||
if let index = haystack.lastIndexMatching(needle) { |
|||
print("\(index) \(needle)") |
|||
} else { |
|||
print("\(needle) is not in haystack") |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
< |
<syntaxhighlight lang="tcl">set haystack {Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo} |
||
foreach needle {Bush Washington} { |
foreach needle {Bush Washington} { |
||
if {[set idx [lsearch -exact $haystack $needle]] == -1} { |
if {[set idx [lsearch -exact $haystack $needle]] == -1} { |
||
Line 2,095: | Line 4,218: | ||
puts "$needle appears at index $idx in the haystack" |
puts "$needle appears at index $idx in the haystack" |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
''' |
'''Extra credit:''' |
||
< |
<syntaxhighlight lang="tcl">set haystack {Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo} |
||
foreach needle {Bush Washington} { |
foreach needle {Bush Washington} { |
||
set indices [lsearch -all -exact $haystack $needle] |
set indices [lsearch -all -exact $haystack $needle] |
||
Line 2,105: | Line 4,228: | ||
puts "$needle appears first at index [lindex $indices 0] and last at [lindex $indices end]" |
puts "$needle appears first at index [lindex $indices 0] and last at [lindex $indices end]" |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|TorqueScript}}== |
|||
--[[User:Elm|Elm]] 03:38, 18 June 2012 (UTC) |
|||
Find multiple needles in a haystack: |
|||
<syntaxhighlight lang="torquescript">function findIn(%haystack,%needles) |
|||
{ |
|||
%hc = getWordCount(%haystack); |
|||
%nc = getWordCount(%needles); |
|||
for(%i=0;%i<%nc;%i++) |
|||
{ |
|||
%nword = getWord(%needles,%i); |
|||
%index[%nword] = -1; |
|||
} |
|||
for(%i=0;%i<%hc;%i++) |
|||
{ |
|||
%hword = getWord(%haystack,%i); |
|||
for(%j=0;%j<%nc;%j++) |
|||
{ |
|||
%nword = getWord(%needles,%j); |
|||
if(%hword $= %nword) |
|||
{ |
|||
%index[%nword] = %i; |
|||
} |
|||
} |
|||
} |
|||
for(%i=0;%i<%nc;%i++) |
|||
{ |
|||
%nword = getWord(%needles,%i); |
|||
%string = %string SPC %nword@"_"@%index[%nword]; |
|||
%string = trim(%string); |
|||
} |
|||
return %string; |
|||
}</syntaxhighlight> |
|||
How to use it: |
|||
<syntaxhighlight lang="torquescript">echo(findIn("Hello world, you are quite sunny today.","quite hello somethingelse"));</syntaxhighlight> |
|||
returns: |
|||
<syntaxhighlight lang="torquescript">=> "quite_4 hello_0 somethingelse_-1"</syntaxhighlight> |
|||
=={{header|TUSCRIPT}}== |
=={{header|TUSCRIPT}}== |
||
< |
<syntaxhighlight lang="tuscript">$$ MODE TUSCRIPT |
||
$$ MODE TUSCRIPT |
|||
SET haystack="Zig'Zag'Wally'Ronald'Bush'Krusty'Charlie'Bush'Bozo" |
SET haystack="Zig'Zag'Wally'Ronald'Bush'Krusty'Charlie'Bush'Bozo" |
||
PRINT "haystack=",haystack |
PRINT "haystack=",haystack |
||
Line 2,123: | Line 4,296: | ||
ENDIF |
ENDIF |
||
RELEASE S_TABLE needle |
RELEASE S_TABLE needle |
||
ENDLOOP |
ENDLOOP</syntaxhighlight> |
||
</lang> |
|||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
haystack=Zig'Zag'Wally'Ronald'Bush'Krusty'Charlie'Bush'Bozo |
haystack=Zig'Zag'Wally'Ronald'Bush'Krusty'Charlie'Bush'Bozo |
||
Line 2,132: | Line 4,305: | ||
haystack contains Wally on position(s): 3 |
haystack contains Wally on position(s): 3 |
||
</pre> |
</pre> |
||
=={{header|UNIX Shell}}== |
|||
{{works with|Almquist Shell}} |
|||
{{works with|bash}} |
|||
{{works with|ksh93}} |
|||
{{works with|pdksh}} |
|||
{{works with|Z Shell}} |
|||
<syntaxhighlight lang="sh">if [ $1 ];then |
|||
haystack="Zip Zag Wally Ronald Bush Krusty Charlie Bush Bozo" |
|||
index=$(echo $haystack|tr " " "\n"|grep -in "^$1$") |
|||
if [ $? = 0 ];then |
|||
quantity_of_hits=$(echo $index|tr " " "\n"|wc -l|tr -d " ") |
|||
first_index=$(echo $index|cut -f 1 -d ":") |
|||
if [ $quantity_of_hits = 1 ];then |
|||
echo The sole index for $1 is: $first_index |
|||
else |
|||
echo The smallest index for $1 is: $first_index |
|||
greatest_index=$(echo $index|tr " " "\n"|tail -1|cut -f 1 -d ":") |
|||
echo "The greatest index for $1 is: $greatest_index";fi |
|||
else echo $1 is absent from haystatck.;fi |
|||
else echo Must provide string to find in haystack.;fi</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
./needle_haystack clay ---> clay is absent from haystatck. |
|||
./needle_haystack charlie ---> The sole index for charlie is: 7 |
|||
./needle_haystack bush ---> The smallest index for bush is: 5 |
|||
The greatest index for bush is: 8</pre> |
|||
=={{header|Ursala}}== |
=={{header|Ursala}}== |
||
The <code>indices</code> function takes a pair <math>(needle,haystack)</math> of any type, treats haystack |
The <code>indices</code> function takes a pair <math>(needle,haystack)</math> 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'. |
|||
as a list, and returns the pair of indices giving the first and last |
|||
The search is expressed by <code>~|</code>, the built-in distributing filter operator. |
|||
positions of needle in it, which are numbered from zero and may be |
|||
<syntaxhighlight lang="ursala">#import std |
|||
equal. If it's not present, an exception is thrown with a diagnostic |
|||
message of 'missing'. The search is expressed by <code>~|</code>, the built in |
|||
distributing filter operator. |
|||
<lang Ursala>#import std |
|||
indices = ||<'missing'>!% ~&nSihzXB+ ~&lrmPE~|^|/~& num</ |
indices = ||<'missing'>!% ~&nSihzXB+ ~&lrmPE~|^|/~& num</syntaxhighlight> |
||
The explanation is somewhat longer than the program. |
The explanation is somewhat longer than the program. |
||
* The <code>^|</code> operator takes a right operand consisting of a pair of functions <math>(f,g)</math>, and returns a function that takes a pair <math>(x,y)</math> to the result <math>(f(x),g(y))</math>. |
* The <code>^|</code> operator takes a right operand consisting of a pair of functions <math>(f,g)</math>, and returns a function that takes a pair <math>(x,y)</math> to the result <math>(f(x),g(y))</math>. |
||
Line 2,166: | Line 4,365: | ||
* The exception throwing operator (<code>%</code>) compels the result of its operand to be returned in a way that bypasses the usual flow of control. |
* The exception throwing operator (<code>%</code>) compels the result of its operand to be returned in a way that bypasses the usual flow of control. |
||
Test program: |
|||
< |
<syntaxhighlight lang="ursala">#cast %nW |
||
test = indices/'bar' <'foo','bar','baz','bar'></ |
test = indices/'bar' <'foo','bar','baz','bar'></syntaxhighlight> |
||
{{out}} |
|||
output: |
|||
<pre>(1,3)</pre> |
<pre>(1,3)</pre> |
||
=={{header|VBA}}== |
|||
<syntaxhighlight lang="vb">Function IsInArray(stringToBeFound As Variant, arr As Variant, _ |
|||
Optional start As Integer = 1, Optional reverse As Boolean = False) As Long |
|||
'Adapted from https://stackoverflow.com/questions/12414168/use-of-custom-data-types-in-vba |
|||
Dim i As Long, lo As Long, hi As Long, stp As Long |
|||
' default return value if value not found in array |
|||
IsInArray = -1 |
|||
If reverse Then |
|||
lo = UBound(arr): hi = start: stp = -1 |
|||
Else |
|||
lo = start: hi = UBound(arr): stp = 1 |
|||
End If |
|||
For i = lo To hi Step stp 'start in stead of LBound(arr) |
|||
If StrComp(stringToBeFound, arr(i), vbTextCompare) = 0 Then |
|||
IsInArray = i |
|||
Exit For |
|||
End If |
|||
Next i |
|||
End Function |
|||
Public Sub search_a_list() |
|||
Dim haystack() As Variant, needles() As Variant |
|||
haystack = [{"Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"}] |
|||
needles = [{"Washington","Bush"}] |
|||
For i = 1 To 2 |
|||
If IsInArray(needles(i), haystack) = -1 Then |
|||
Debug.Print needles(i); " not found in haystack." |
|||
Else |
|||
Debug.Print needles(i); " is at position "; CStr(IsInArray(needles(i), haystack)); "."; |
|||
Debug.Print " And last position is "; |
|||
Debug.Print CStr(IsInArray(needles(i), haystack, 1, True)); "." |
|||
End If |
|||
Next i |
|||
End Sub</syntaxhighlight>{{out}}<pre>Washington not found in haystack. |
|||
Bush is at position 5. And last position is 8.</pre> |
|||
=={{header|VBScript}}== |
|||
Shamelessly derived from the BASIC version. |
|||
<syntaxhighlight lang="vb"> |
|||
data = "foo,bar,baz,quux,quuux,quuuux,bazola,ztesch,foo,bar,thud,grunt," &_ |
|||
"foo,bar,bletch,foo,bar,fum,fred,jim,sheila,barney,flarp,zxc," &_ |
|||
"spqr,wombat,shme,foo,bar,baz,bongo,spam,eggs,snork,foo,bar," &_ |
|||
"zot,blarg,wibble,toto,titi,tata,tutu,pippo,pluto,paperino,aap," &_ |
|||
"noot,mies,oogle,foogle,boogle,zork,gork,bork" |
|||
haystack = Split(data,",") |
|||
Do |
|||
WScript.StdOut.Write "Word to search for? (Leave blank to exit) " |
|||
needle = WScript.StdIn.ReadLine |
|||
If needle <> "" Then |
|||
found = 0 |
|||
For i = 0 To UBound(haystack) |
|||
If UCase(haystack(i)) = UCase(needle) Then |
|||
found = 1 |
|||
WScript.StdOut.Write "Found " & Chr(34) & needle & Chr(34) & " at index " & i |
|||
WScript.StdOut.WriteLine |
|||
End If |
|||
Next |
|||
If found < 1 Then |
|||
WScript.StdOut.Write Chr(34) & needle & Chr(34) & " not found." |
|||
WScript.StdOut.WriteLine |
|||
End If |
|||
Else |
|||
Exit do |
|||
End If |
|||
Loop |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre>F:\VBScript>cscript /nologo search_a_list.vbs |
|||
Word to search for? (Leave blank to exit) foo |
|||
Found "foo" at index 0 |
|||
Found "foo" at index 8 |
|||
Found "foo" at index 12 |
|||
Found "foo" at index 15 |
|||
Found "foo" at index 27 |
|||
Found "foo" at index 34 |
|||
Word to search for? (Leave blank to exit) bar |
|||
Found "bar" at index 1 |
|||
Found "bar" at index 9 |
|||
Found "bar" at index 13 |
|||
Found "bar" at index 16 |
|||
Found "bar" at index 28 |
|||
Found "bar" at index 35 |
|||
Word to search for? (Leave blank to exit) fff |
|||
"fff" not found. |
|||
Word to search for? (Leave blank to exit) |
|||
F:\VBScript></pre> |
|||
=={{header|V (Vlang)}}== |
|||
<syntaxhighlight lang="Rust"> |
|||
const ( |
|||
haystacks = ["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Bozo"] |
|||
needles = ["Bush", "washington", "Wally"] |
|||
) |
|||
fn main() { |
|||
mut list, mut index, mut count, mut missing := "", "", "", "" |
|||
for nee in needles { |
|||
for idx, hay in haystacks { |
|||
if nee == hay { |
|||
count = "${haystacks.str().count(nee)}" |
|||
if list.contains(nee) { |
|||
index += ", ${idx}" |
|||
list = "Found: ${nee}; Index: ${index}; Count: ${count}\n" |
|||
} |
|||
else { |
|||
index = "${idx}" |
|||
list += "Found: ${nee}; Index: ${index}; Count: ${count}\n" |
|||
} |
|||
} |
|||
} |
|||
if nee !in haystacks && !missing.contains(nee) {missing += "Missing: ${nee}\n"} |
|||
} |
|||
list += missing |
|||
println(list.all_before_last('\n')) |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Found: Bush; Index: 4, 7; Count: 2 |
|||
Found: Wally; Index: 2; Count: 1 |
|||
Missing: washington |
|||
</pre> |
|||
=={{header|Wart}}== |
|||
Wart uses the function <code>pos</code> to search a list for an element. |
|||
Here's how it's implemented: |
|||
<syntaxhighlight lang="python">def (pos x (seq | (head ... tail)) n) |
|||
default n :to 0 |
|||
if seq |
|||
if (head = x) |
|||
n |
|||
(pos x tail n+1)</syntaxhighlight> |
|||
{{out|Usage}} |
|||
<pre>pos 3 '(1 2 3 4 5) |
|||
=> 2 |
|||
pos 24 '(1 2 3 4 5) |
|||
=> nil</pre> |
|||
=={{header|Wren}}== |
|||
{{libheader|Wren-seq}} |
|||
<syntaxhighlight lang="wren">import "./seq" for Lst |
|||
var find = Fn.new { |haystack, needle| |
|||
var res = Lst.indicesOf(haystack, needle) |
|||
if (!res[0]) Fiber.abort("Needle not found in haystack.") |
|||
System.print("The needle occurs %(res[1]) time(s) in the haystack.") |
|||
if (res[1] == 1) { |
|||
System.print("It occurs at index %(res[2][0])") |
|||
} else { |
|||
System.print("It first occurs at index %(res[2][0])") |
|||
System.print("It last occurs at index %(res[2][-1])") |
|||
} |
|||
System.print() |
|||
} |
|||
var haystack = ["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Boz", "Zag"] |
|||
System.print("The haystack is:\n%(haystack)\n") |
|||
var needles = ["Wally", "Bush", "Zag", "George"] |
|||
for (needle in needles) { |
|||
System.print("The needle is %(needle).") |
|||
find.call(haystack, needle) |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
The haystack is: |
|||
[Zig, Zag, Wally, Ronald, Bush, Krusty, Charlie, Bush, Boz, Zag] |
|||
The needle is Wally. |
|||
The needle occurs 1 time(s) in the haystack. |
|||
It occurs at index 2 |
|||
The needle is Bush. |
|||
The needle occurs 2 time(s) in the haystack. |
|||
It first occurs at index 4 |
|||
It last occurs at index 7 |
|||
The needle is Zag. |
|||
The needle occurs 2 time(s) in the haystack. |
|||
It first occurs at index 1 |
|||
It last occurs at index 9 |
|||
The needle is George. |
|||
Needle not found in haystack. |
|||
[./search_list line 5] in new(_) block argument |
|||
[./search_list line 21] in (script) |
|||
</pre> |
|||
=={{header|XPL0}}== |
|||
<syntaxhighlight lang="xpl0">\Based on C example: |
|||
include c:\cxpl\stdlib; \provides StrCmp routine, etc. |
|||
int Haystack; \('int' is used instead of 'char' for 2D array) |
|||
func Search(Str, First); \Return first (or last) index for string in haystack |
|||
char Str; int First; |
|||
int I, SI; |
|||
[I:= 0; SI:= 0; |
|||
repeat if StrCmp(Str, Haystack(I)) = 0 then |
|||
[if First then return I; |
|||
SI:= I; \save index |
|||
]; |
|||
I:= I+1; |
|||
until Haystack(I) = 0; |
|||
return SI; |
|||
]; |
|||
[Haystack:= ["Zig", "Zag", "Wally", "Ronald", "Bush", |
|||
"Krusty", "Charlie", "Bush", "Boz", "Zag", 0]; |
|||
Text(0, "Bush is at "); IntOut(0, Search("Bush", true)); CrLf(0); |
|||
if Search("Washington", true) = 0 then |
|||
Text(0, "Washington is not in the haystack^M^J"); |
|||
Text(0, "First index for Zag: "); IntOut(0, Search("Zag", true)); CrLf(0); |
|||
Text(0, "Last index for Zag: "); IntOut(0, Search("Zag", false)); CrLf(0); |
|||
]</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Bush is at 4 |
|||
Washington is not in the haystack |
|||
First index for Zag: 1 |
|||
Last index for Zag: 9 |
|||
</pre> |
|||
=={{header|Yorick}}== |
=={{header|Yorick}}== |
||
< |
<syntaxhighlight lang="yorick">haystack = ["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Bozo"]; |
||
needles = ["Bush", "Washington"]; |
needles = ["Bush", "Washington"]; |
||
for(i = 1; i <= numberof(needles); i++) { |
for(i = 1; i <= numberof(needles); i++) { |
||
Line 2,183: | Line 4,609: | ||
if(numberof(w) > 1) |
if(numberof(w) > 1) |
||
write, format="Needle %s appears last at index %d\n", needles(i), w(0); |
write, format="Needle %s appears last at index %d\n", needles(i), w(0); |
||
}</ |
}</syntaxhighlight> |
||
=={{header|zkl}}== |
|||
<syntaxhighlight lang="zkl">L("Krusty","Charlie","Bozo","Bozo").index("Charlie") //--> 1 |
|||
L("Krusty","Charlie","Bozo","Bozo").index("fred") //--> throws index error</syntaxhighlight> |
|||
Find last needle: |
|||
<syntaxhighlight lang="zkl">haystack:=L("Krusty","Charlie","Bozo","Bozo"); |
|||
haystack.filterNs('==("Bozo"))[-1]; // -->3, indexError if not found |
|||
haystack.len() - 1 - haystack.reverse().index("Bozo"); // or this</syntaxhighlight> |
|||
Use a bit bucket of ASCIIZ strings |
|||
<syntaxhighlight lang="zkl">haystack:=Data(0,String,"Krusty","Charlie","Bozo","Bozo"); |
|||
if((n:=haystack.findString("Charlie")) != Void) n else throw(Exception.IndexError); |
|||
//-->7</syntaxhighlight> |
Latest revision as of 17:37, 7 August 2024
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
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.
Return the largest index to a needle that has multiple occurrences in the haystack.
11l
V haystack = [‘Zig’, ‘Zag’, ‘Wally’, ‘Ronald’, ‘Bush’, ‘Krusty’, ‘Charlie’, ‘Bush’, ‘Bozo’]
L(needle) (‘Washington’, ‘Bush’)
X.try
print(haystack.index(needle)‘ ’needle)
X.catch ValueError
print(needle‘ is not in haystack’)
- Output:
Washington is not in haystack 4 Bush
ACL2
(defun index-of-r (e xs i)
(cond ((endp xs) nil)
((equal e (first xs)) i)
(t (index-of-r e (rest xs) (1+ i)))))
(defun index-of (e xs)
(index-of-r e xs 0))
Acornsoft Lisp
Acornsoft Lisp does not have strings, so symbols would be used instead. That also allows us to use eq
as the test.
(defun first-index (word words (i . 0))
(loop
(until (null words)
(error word '! is! missing))
(until (eq word (car words))
i)
(setq words (cdr words))
(setq i (add1 i))))
(defun last-index (word words (i . 0) (last-i . nil))
(loop
(until (null words)
(cond (last-i) (t (error word '! is! missing))))
(cond ((eq word (car words))
(setq last-i i)))
(setq words (cdr words))
(setq i (add1 i))))
Action!
DEFINE PTR="CARD"
INT FUNC Search(PTR ARRAY texts INT count CHAR ARRAY text)
INT i
FOR i=0 TO count-1
DO
IF SCompare(texts(i),text)=0 THEN
RETURN (i)
FI
OD
RETURN (-1)
PROC Test(PTR ARRAY texts INT count CHAR ARRAY text)
INT index
index=Search(texts,count,text)
IF index=-1 THEN
PrintF("""%S"" is not in haystack.%E",text)
ELSE
PrintF("""%S"" is on index %I in haystack.%E",text,index)
FI
RETURN
PROC Main()
PTR ARRAY texts(7)
texts(0)="Monday"
texts(1)="Tuesday"
texts(2)="Wednesday"
texts(3)="Thursday"
texts(4)="Friday"
texts(5)="Saturday"
texts(6)="Sunday"
Test(texts,7,"Monday")
Test(texts,7,"Sunday")
Test(texts,7,"Thursday")
Test(texts,7,"Weekend")
RETURN
- Output:
Screenshot from Atari 8-bit computer
"Monday" is on index 0 in haystack. "Sunday" is on index 6 in haystack. "Thursday" is on index 3 in haystack. "Weekend" is not in haystack.
ActionScript
Using the built-in Error class
var list:Vector.<String> = Vector.<String>(["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Boz", "Zag"]);
function lowIndex(listToSearch:Vector.<String>, searchString:String):int
{
var index:int = listToSearch.indexOf(searchString);
if(index == -1)
throw new Error("String not found: " + searchString);
return index;
}
function highIndex(listToSearch:Vector.<String>, searchString:String):int
{
var index:int = listToSearch.lastIndexOf(searchString);
if(index == -1)
throw new Error("String not found: " + searchString);
return index;
}
Using a custom error
In StringNotFoundError.as:
package {
public class StringNotFoundError extends Error {
public function StringNotFoundError(message:String) {
super(message);
}
}
}
In a separate file:
import StringNotFoundError;
var list:Vector.<String> = Vector.<String>(["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Boz", "Zag"]);
function lowIndex(listToSearch:Vector.<String>, searchString:String):int
{
var index:int = listToSearch.indexOf(searchString);
if(index == -1)
throw new StringNotFoundError("String not found: " + searchString);
return index;
}
function highIndex(listToSearch:Vector.<String>, searchString:String):int
{
var index:int = listToSearch.lastIndexOf(searchString);
if(index == -1)
throw new StringNotFoundError("String not found: " + searchString);
return index;
}
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;
- Output:
Washington is not in Bushat 5
Aime
void
search(list l, text s)
{
integer i;
i = 0;
while (i < ~l) {
if (l[i] == s) {
break;
}
i += 1;
}
o_(s, " is ", i == ~l ? "not in the haystack" : "at " + itoa(i), "\n");
}
integer
main(void)
{
list l;
l = l_effect("Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty",
"Charlie", "Bush", "Boz", "Zag");
__ucall(search, 1, 1, l, "Bush", "Washington", "Zag");
return 0;
}
- Output:
Bush is at 4 Washington is not in the haystack Zag is at 1
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
);
test:(
[]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
);
test:(
[]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
Arturo
haystack: [Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo]
loop [Bush Washington] 'needle [
i: index haystack needle
if? empty? i -> panic ~"|needle| is not in haystack"
else -> print [i needle]
]
- Output:
4 Bush >> Error | Washington is not in haystack
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"
}
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!)
#! /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";
}
}
BASIC
DATA foo, bar, baz, quux, quuux, quuuux, bazola, ztesch, foo, bar, thud, grunt
DATA foo, bar, bletch, foo, bar, fum, fred, jim, sheila, barney, flarp, zxc
DATA spqr, wombat, shme, foo, bar, baz, bongo, spam, eggs, snork, foo, bar
DATA zot, blarg, wibble, toto, titi, tata, tutu, pippo, pluto, paperino, aap
DATA noot, mies, oogle, foogle, boogle, zork, gork, bork
DIM haystack(54) AS STRING
DIM needle AS STRING, found AS INTEGER, L0 AS INTEGER
FOR L0 = 0 TO 54
READ haystack(L0)
NEXT
DO
INPUT "Word to search for? (Leave blank to exit) ", needle
IF needle <> "" THEN
FOR L0 = 0 TO UBOUND(haystack)
IF UCASE$(haystack(L0)) = UCASE$(needle) THEN
found = 1
PRINT "Found "; CHR$(34); needle; CHR$(34); " at index "; LTRIM$(STR$(L0))
END IF
NEXT
IF found < 1 THEN
PRINT CHR$(34); needle; CHR$(34); " not found"
END IF
ELSE
EXIT DO
END IF
LOOP
- Output:
Word to search for? (Leave blank to exit) foo Found "foo" at index 0 Found "foo" at index 8 Found "foo" at index 12 Found "foo" at index 15 Found "foo" at index 27 Found "foo" at index 34 Word to search for? (Leave blank to exit) bar Found "bar" at index 1 Found "bar" at index 9 Found "bar" at index 13 Found "bar" at index 16 Found "bar" at index 28 Found "bar" at index 35 Word to search for? (Leave blank to exit) baz Found "baz" at index 2 Found "baz" at index 29 Word to search for? (Leave blank to exit)
BASIC256
list$ = "mouse,hat,cup,deodorant,television,soap,methamphetamine,severed cat heads,cup"
n$ = explode(list$, ",")
t = 0 : j = 0
input string "Enter string to search: ", linea$
for i = 0 to n$[?]-1
if linea$ = n$[i] then
if not t then print "First index for "; linea$; ": "; i
t = i
j += 1
end if
next
if t = 0 then
print "String not found in list"
else
if j > 1 then print "Last index for "; linea$; ": "; t
end if
BBC BASIC
DIM haystack$(27)
haystack$() = "alpha","bravo","charlie","delta","echo","foxtrot","golf", \
\ "hotel","india","juliet","kilo","lima","mike","needle", \
\ "november","oscar","papa","quebec","romeo","sierra","tango", \
\ "needle","uniform","victor","whisky","x-ray","yankee","zulu"
needle$ = "needle"
maxindex% = DIM(haystack$(), 1)
FOR index% = 0 TO maxindex%
IF needle$ = haystack$(index%) EXIT FOR
NEXT
IF index% <= maxindex% THEN
PRINT "First found at index "; index%
FOR last% = maxindex% TO 0 STEP -1
IF needle$ = haystack$(last%) EXIT FOR
NEXT
IF last%<>index% PRINT "Last found at index "; last%
ELSE
ERROR 100, "Not found"
ENDIF
IS-BASIC
100 PROGRAM "Search.bas"
110 STRING A$(1 TO 55)*8
120 FOR I=1 TO 55
130 READ A$(I)
140 PRINT A$(I);" ";
150 NEXT
160 DO
170 PRINT :INPUT PROMPT "Word to seatch for? (Leave blank to exit) ":S$
180 LET S$=LCASE$(LTRIM$(RTRIM$(S$))):LET FOUND=0
190 IF S$="" THEN EXIT DO
200 FOR I=LBOUND(A$) TO UBOUND(A$)
210 IF A$(I)=S$ THEN LET FOUND=-1:PRINT "Found """;S$;""" at index";I
220 NEXT
230 IF NOT FOUND THEN PRINT """";S$;""" not found."
240 LOOP
250 DATA foo,bar,baz,quux,quuux,quuuux,bazola,ztesch,foo,bar,thud,grunt,foo,bar,bletch,foo,bar,fum,fred,jim,sheila,barney,flarp,zxc
260 DATA spqr,wombat,shme,foo,bar,baz,bongo,spam,eggs,snork,foo,bar,zot,blarg,wibble,toto,titi,tata,tutu,pippo,pluto,paperino,aap,noot,mies,oogle,foogle,boogle,zork,gork,bork
FreeBASIC
FreeBASIC doesn't have exceptions so we use a different approach to check if the needle is present or not in the haystack:
' FB 1.05.0 Win64
' Works FB 1.05.0 Linux Mint 64
Function tryFindString(s() As String, search As String, ByRef index As Integer) As Boolean
Dim length As Integer = UBound(s) - LBound(s) + 1
If length = 0 Then
index = LBound(s) - 1 '' outside array
Return False
End If
For i As Integer = LBound(s) To UBound(s)
If s(i) = search Then
index = i '' first occurrence
Return True
End If
Next
index = LBound(s) - 1 '' outside array
Return False
End Function
Function tryFindLastString(s() As String, search As String, ByRef index As Integer) As Boolean
Dim length As Integer = UBound(s) - LBound(s) + 1
If length = 0 Then
index = LBound(s) - 1 '' outside array
Return False
End If
Dim maxIndex As Integer = LBound(s) - 1 '' outside array
For i As Integer = LBound(s) To UBound(s)
If s(i) = search Then
maxIndex = i
End If
Next
If maxIndex > LBound(s) - 1 Then
index = maxIndex '' last occurrence
Return True
Else
Return False
End If
End Function
Dim haystack(1 To 9) As String = {"Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Bozo"}
Dim needle(1 To 4) As String = {"Zag", "Krusty", "Washington", "Bush"}
Dim As Integer index
Dim As Boolean found
For i As Integer = 1 To 4
found = tryFindString(haystack(), needle(i), index)
If found Then
Print needle(i); " found first at index"; index
Else
Print needle(i); " is not present"
End If
Next
found = tryFindLastString(haystack(), needle(4), index)
If found Then
Print needle(4); " found last at index"; index
Else
Print needle(4); " is not present"
End If
Print
Print "Press any key to quit"
Sleep
- Output:
Zag found first at index 2 Krusty found first at index 6 Washington is not present Bush found first at index 5 Bush found last at index 8
Gambas
Click this link to run this code
Public Sub Main()
Dim sHaystack As String[] = ["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Boz", "Zag"]
Dim sNeedle As String = "Charlie"
Dim sOutput As String = "No needle found!"
Dim siCount As Short
For siCount = 0 To sHaystack.Max
If sNeedle = sHaystack[siCount] Then
sOutPut = sNeedle & " found at index " & Str(siCount)
Break
End If
Next
Print sOutput
End
Output:
Charlie found at index 6
Liberty BASIC
haystack$="apple orange pear cherry melon peach banana needle blueberry mango strawberry needle "
haystack$=haystack$+"pineapple grape kiwi blackberry plum raspberry needle cranberry apricot"
idx=1
do until word$(haystack$,idx)=""
idx=idx+1
loop
total=idx-1
needle$="needle"
'index of first occurrence
for i = 1 to total
if word$(haystack$,i)=needle$ then exit for
next
print needle$;" first found at index ";i
'index of last occurrence
for j = total to 1
if word$(haystack$,j)=needle$ then exit for
next
print needle$;" last found at index ";j
if i<>j then
print "Multiple instances of ";needle$
else
print "Only one instance of ";needle$;" in list."
end if
'raise exception
needle$="cauliflower"
for k=1 to total
if word$(haystack$,k)=needle$ then exit for
next
if k>total then
print needle$;" not found in list."
else
print needle$;" found at index ";k
end if
PowerBASIC
FUNCTION PBMAIN () AS LONG
DIM haystack(54) AS STRING
ARRAY ASSIGN haystack() = "foo", "bar", "baz", "quux", "quuux", "quuuux", _
"bazola", "ztesch", "foo", "bar", "thud", "grunt", "foo", _
"bar", "bletch", "foo", "bar", "fum", "fred", "jim", _
"sheila", "barney", "flarp", "zxc", "spqr", ";wombat", "shme", _
"foo", "bar", "baz", "bongo", "spam", "eggs", "snork", "foo", _
"bar", "zot", "blarg", "wibble", "toto", "titi", "tata", _
"tutu", "pippo", "pluto", "paperino", "aap", "noot", "mies", _
"oogle", "foogle", "boogle", "zork", "gork", "bork"
DIM needle AS STRING, found AS LONG, lastFound AS LONG
DO
needle = INPUTBOX$("Word to search for? (Leave blank to exit)")
IF needle <> "" THEN
' collate ucase -> case insensitive
ARRAY SCAN haystack(), COLLATE UCASE, = needle, TO found
IF found > 0 THEN
lastFound = found
MSGBOX "Found """ & needle & """ at index " & TRIM$(STR$(found - 1))
IF found < UBOUND(haystack) THEN
DO
ARRAY SCAN haystack(lastFound), COLLATE UCASE, = needle, TO found
IF found > 0 THEN
MSGBOX "Another occurence of """ & needle & """ at index " & _
TRIM$(STR$(found + lastFound - 1))
lastFound = found + lastFound
ELSE
MSGBOX "No more occurences of """ & needle & """ found"
EXIT DO 'will exit inner DO, not outer
END IF
LOOP
END IF
ELSE
MSGBOX "No occurences of """ & needle & """ found"
END IF
ELSE
EXIT DO
END IF
LOOP
END FUNCTION
PureBasic
If OpenConsole() ; Open a simple console to interact with user
NewList Straws.s()
Define Straw$, target$="TBA"
Define found
Restore haystack ; Read in all the straws of the haystack.
Repeat
Read.s Straw$
If Straw$<>""
AddElement(Straws())
Straws()=UCase(Straw$)
Continue
Else
Break
EndIf
ForEver
While target$<>""
Print(#CRLF$+"Enter word to search for (leave blank to quit) :"): target$=Input()
ResetList(Straws()): found=#False
While NextElement(Straws())
If UCase(target$)=Straws()
found=#True
PrintN(target$+" found as index #"+Str(ListIndex(Straws())))
EndIf
Wend
If Not found
PrintN("Not found.")
EndIf
Wend
EndIf
DataSection
haystack:
Data.s "Zig","Zag","Zig","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo",""
EndDataSection
Run BASIC
haystack$ = ("Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo Bush ")
needle$ = "Zag Wally Bush Chicken"
while word$(needle$,i+1," ") <> ""
i = i + 1
thisNeedle$ = word$(needle$,i," ") + " "
j = instr(haystack$,thisNeedle$)
k1 = 0
k = instr(haystack$,thisNeedle$,j+1)
while k <> 0
k1 = k
k = instr(haystack$,thisNeedle$,k+1)
wend
if j <> 0 then
print thisNeedle$;" located at:";j;
if k1 <> 0 then print " Last position located at:";k1;
print
else
print thisNeedle$;" is not in the list"
end if
wend
- Output:
Zag located at:5 Wally located at:9 Bush located at:22 Last position located at:52 Chicken is not in the list
Yabasic
list$ = "mouse,hat,cup,deodorant,television,soap,methamphetamine,severed cat heads,cup"
dim item$(1)
n = token(list$, item$(), ",")
line input "Enter string to search: " line$
for i = 1 to n
if line$ = item$(i) then
if not t print "First index for ", line$, ": ", i
t = i
j = j + 1
end if
next
if t = 0 then
print "String not found in list"
else
if j > 1 print "Last index for ", line$, ": ", t
end if
Batch File
The index of this simple implementation is 1-based. The "haystack" data are borrowed from the BASIC implementation.
@echo off
setlocal enabledelayedexpansion
%==Sample list==%
set "data=foo, bar, baz, quux, quuux, quuuux, bazola, ztesch, foo, bar, thud, grunt"
set "data=%data% foo, bar, bletch, foo, bar, fum, fred, jim, sheila, barney, flarp, zxc"
set "data=%data% spqr, wombat, shme, foo, bar, baz, bongo, spam, eggs, snork, foo, bar"
set "data=%data% zot, blarg, wibble, toto, titi, tata, tutu, pippo, pluto, paperino, aap"
set "data=%data% noot, mies, oogle, foogle, boogle, zork, gork, bork"
%==Sample "needles" [whitespace is the delimiter]==%
set "needles=foo bar baz jim bong"
%==Counting and Seperating each Data==%
set datalen=0
for %%. in (!data!) do (
set /a datalen+=1
set data!datalen!=%%.
)
%==Do the search==%
for %%A in (!needles!) do (
set "first="
set "last="
set "found=0"
for /l %%B in (1,1,%datalen%) do (
if "!data%%B!" == "%%A" (
set /a found+=1
if !found! equ 1 set first=%%B
set last=%%B
)
)
if !found! equ 0 echo."%%A": Not found.
if !found! equ 1 echo."%%A": Found once in index [!first!].
if !found! gtr 1 echo."%%A": Found !found! times. First instance:[!first!] Last instance:[!last!].
)
%==We are done==%
echo.
pause
- Output:
"foo": Found 6 times. First instance:[1] Last instance:[35]. "bar": Found 6 times. First instance:[2] Last instance:[36]. "baz": Found 2 times. First instance:[3] Last instance:[30]. "jim": Found once in index [20]. "bong": Not found. Press any key to continue . . .
BQN
Generally, ⊐
(Index Of) is used to find the indices of the right argument array's elements in the left argument. It returns the length of the left argument 𝕨
if the argument is not present.
The given IndexOf
function is written to satisfy question requirements (throwing exceptions), and it is not recommended for use in production.
list ← ⟨"Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Boz", "Zag"⟩
IndexOf ← {
("Error: '" ∾𝕩∾ "' Not found in list") ! (≠𝕨)≠ind ← ⊑𝕨⊐⋈𝕩
ind
}
•Show list ⊐ "Wally"‿"Hi" # intended
•Show list IndexOf "Wally"
list IndexOf "Hi"
⟨ 2 10 ⟩
2
! "Error: 'Hi' Not found in list"
("Error: '" ∾𝕩∾ "' Not found in list") ! (≠𝕨)≠ind ← ⊑𝕨⊐⋈𝕩
^
list IndexOf "Hi"
^^^^^^^
Bracmat
For both subtasks, pattern matching is used. The second subtasks proceeds in two steps. First, the first word that occurs twice is found (if it exists). Then, the last occurrence of this word is found using forced backtracking (see the ~
node) until failure.
( return the largest index to a needle that has multiple
occurrences in the haystack and print the needle
: ?list
& ( !list:? haystack [?index ?
& out$("The word 'haystack' occurs at 1-based index" !index)
| out$"The word 'haystack' does not occur"
)
& ( !list
: ? %@?needle ? !needle ?
: ( ? !needle [?index (?&~)
| ?
& out
$ ( str
$ ( "The word '"
!needle
"' occurs more than once. The last 1-based index is "
!index
)
)
)
| out$"No word occurs more than once."
)
);
- Output:
The word 'haystack' occurs at 1-based index 14 The word 'the' occurs more than once. The last 1-based index is 17
Burlesque
blsq ) {"Zig" "Zag" "Wally" "Bush" "Ronald" "Bush"}"Bush"Fi
3
If you want all indices:
blsq ) {"Zig" "Zag" "Wally" "Bush" "Ronald" "Bush"}{"Bush"==}fI
{3 5}
C
#include <stdio.h>
#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;
}
- Output:
Bush is at 4 Washington is not in the haystack First index for Zag: 1 Last index for Zag: 9
C#
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);
}
}
}
C++
The following code shows three different ways to solve the task.
#include <string>
#include <algorithm>
#include <iterator>
#include <cstddef>
#include <exception>
#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");
}
- 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++11
/* new c++-11 features
* list class
* initialization strings
* auto typing
* lambda functions
* noexcept
* find
* for/in loop
*/
#include <iostream> // std::cout
#include <algorithm> // std::find
#include <list> // std::list
#include <vector> // std::vector
#include <string> // string::basic_string
using namespace std; // saves typing of "std::" before everything
int main()
{
// initialization lists
// create objects and fully initialize them with given values
list<string> l { "Zig", "Zag", "Wally", "Homer", "Madge",
"Watson", "Ronald", "Bush", "Krusty", "Charlie",
"Bush", "Bush", "Boz", "Zag" };
list<string> n { "Bush" , "Obama", "Homer", "Sherlock" };
// lambda function with auto typing
// auto is easier to write than looking up the complicated
// specialized iterator type that is actually returned.
// Just know that it returns an iterator for the list at the position found,
// or throws an exception if s in not in the list.
// runtime_error is used because it can be initialized with a message string.
auto contains = [](list<string> l, string s) throw(runtime_error)
{
auto r = find(begin(l), end(l), s );
if( r == end(l) )
throw runtime_error( s + " not found" );
return r;
};
// returns an int vector with the indexes of the search string
// The & is a "default capture" meaning that it "allows in"
// the variables that are in scope where it is called by their
// name to simplify things.
auto index = [&](list<string> l, string s) noexcept
{
vector<int> index_v;
int idx = 0;
for(const string& r : l)
{
if( s.compare(r) == 0 ) // match -- add to vector
index_v.push_back(idx);
idx++;
}
// even though index_v is local to the lambda function,
// c++11 move semantics does what you want and returns it
// live and intact instead of destroying it or returning a copy.
// (very efficient for large objects!)
return index_v;
};
// range-based for loop
// s is a read-only reference, not a copy
for (const string& s : n) // new iteration syntax is simple and intuitive
{
try
{
auto cont = contains( l , s); // checks if there is any match
if( cont != l.end() ) // found at least one
{
vector<int> vf = index( l, s );
cout << "l contains: " << s << " at " ;
for(auto x : vf) // auto will resolve to int
{ cout << x << " "; } // if vector is empty this doesn't run
cout << "\n";
}
}
catch (const runtime_error& r) // string not found
{
cout << r.what() << "\n";
continue; // try next string
}
} //for
return 0;
} // main
/* end */
- Output:
l contains: Bush at 7 10 11 Obama not found l contains: Homer at 3 Sherlock not found
Ceylon
shared test void searchAListTask() {
value haystack = [
"Zig", "Zag", "Wally", "Ronald", "Bush",
"Krusty", "Charlie", "Bush", "Bozo"];
assert(exists firstIdx = haystack.firstOccurrence("Bush"));
assert(exists lastIdx = haystack.lastOccurrence("Bush"));
assertEquals(firstIdx, 4);
assertEquals(lastIdx, 7);
}
Clojure
(let [haystack ["Zig" "Zag" "Wally" "Ronald" "Bush" "Krusty" "Charlie" "Bush" "Bozo"]]
(let [idx (.indexOf haystack "Zig")]
(if (neg? idx)
(throw (Error. "item not found."))
idx)))
Extra credit: Since Clojure vectors implement java.util.List, you can switch .indexOf for .lastIndexOf to find the highest index of your value.
CLU
% Search an indexable, ordered collection.
% The collection needs to provide `indexes' and `fetch';
% the element type needs to provide `equal'.
search = proc [T, U: type] (haystack: T, needle: U)
returns (int) signals (not_found)
where T has indexes: itertype (T) yields (int),
fetch: proctype (T,int) returns (U) signals (bounds),
U has equal: proctype (U,U) returns (bool)
for i: int in T$indexes(haystack) do
if needle = haystack[i] then return (i) end
end
signal not_found
end search
start_up = proc ()
as = array[string]
str_search = search[as,string]
po: stream := stream$primary_output()
haystack: as := as$
["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"]
needles: as := as$
["Ronald","McDonald","Bush","Obama"]
for needle: string in as$elements(needles) do
stream$puts(po, needle || ": ")
stream$putl(po, int$unparse(str_search(haystack,needle)))
except when not_found:
stream$putl(po, "not found")
end
end
end start_up
- Output:
Ronald: 4 McDonald: not found Bush: 5 Obama: not found
COBOL
*> This is written to COBOL85, which does not include exceptions.
IDENTIFICATION DIVISION.
PROGRAM-ID. Search-List.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 haystack-area.
78 Haystack-Size VALUE 10.
03 haystack-data.
05 FILLER PIC X(7) VALUE "Zig".
05 FILLER PIC X(7) VALUE "Zag".
05 FILLER PIC X(7) VALUE "Wally".
05 FILLER PIC X(7) VALUE "Ronald".
05 FILLER PIC X(7) VALUE "Bush".
05 FILLER PIC X(7) VALUE "Krusty".
05 FILLER PIC X(7) VALUE "Charlie".
05 FILLER PIC X(7) VALUE "Bush".
05 FILLER PIC X(7) VALUE "Boz".
05 FILLER PIC X(7) VALUE "Zag".
03 haystack-table REDEFINES haystack-data.
05 haystack PIC X(7) OCCURS Haystack-Size TIMES
INDEXED BY haystack-index.
01 needle PIC X(7).
PROCEDURE DIVISION.
main.
MOVE "Bush" TO needle
PERFORM find-needle
MOVE "Goofy" TO needle
PERFORM find-needle
* *> Extra task
MOVE "Bush" TO needle
PERFORM find-last-of-needle
GOBACK
.
find-needle.
SEARCH haystack
AT END
DISPLAY needle " not found."
WHEN haystack (haystack-index) = needle
DISPLAY "Found " needle " at " haystack-index "."
END-SEARCH
.
find-last-of-needle.
PERFORM VARYING haystack-index FROM Haystack-Size BY -1
UNTIL haystack-index = 0
OR haystack (haystack-index) = needle
END-PERFORM
IF haystack-index = 0
DISPLAY needle " not found."
ELSE
DISPLAY "Found last of " needle " at " haystack-index "."
END-IF
.
- Output:
Found Bush at +000000005. Goofy not found. Found last of Bush at +000000008.
Common 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"))))))
- Output:
WASHINGTON is not in haystack 4 BUSH
The position function solves this task elegantly.
CL-USER> (defparameter *list* '(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo))
*LIST*
CL-USER> (position 'Bush *list*)
4
CL-USER> (position 'Bush *list* :from-end t)
7
CL-USER> (position 'Washington *list*)
NIL
D
import std.algorithm, std.range, std.string;
auto firstIndex(R, T)(R hay, T needle) {
auto i = countUntil(hay, needle);
if (i == -1)
throw new Exception("No needle found in haystack");
return i;
}
auto lastIndex(R, T)(R hay, T needle) {
return walkLength(hay) - firstIndex(retro(hay), needle) - 1;
}
void main() {
auto h = split("Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo");
assert(firstIndex(h, "Bush") == 4);
assert(lastIndex(h, "Bush") == 7);
}
Delphi
program Needle;
{$APPTYPE CONSOLE}
uses
SysUtils, Classes;
var
list: TStringList;
needle: string;
ind: Integer;
begin
list := TStringList.Create;
try
list.Append('triangle');
list.Append('fork');
list.Append('limit');
list.Append('baby');
list.Append('needle');
list.Sort;
needle := 'needle';
ind := list.IndexOf(needle);
if ind < 0 then
raise Exception.Create('Needle not found')
else begin
Writeln(ind);
Writeln(list[ind]);
end;
Readln;
finally
list.Free;
end;
end.
- Output:
3 needle
DWScript
var haystack : array of String = ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"];
function Find(what : String) : Integer;
begin
Result := haystack.IndexOf(what);
if Result < 0 then
raise Exception.Create('not found');
end;
PrintLn(Find("Ronald")); // 3
PrintLn(Find('McDonald')); // exception
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
EasyLang
haystack$[] = [ "Zig" "Zag" "Wally" "Ronald" "Bush" "Krusty" "Charlie" "Bush" "Boz" "Zag" ]
#
func getind needle$ .
for i to len haystack$[]
if haystack$[i] = needle$
return i
.
.
return 0
.
# arrays are 1 based
for n$ in [ "Bush" "Washington" ]
h = getind n$
if h = 0
print n$ & " not found"
else
print n$ & " found at " & h
.
.
Ecstasy
The List
type has an indexOf()
method, and the Array
type is a List
:
module test {
@Inject Console console;
void run() {
String[] haystack = ["this", "needle", "is", "a", "test"];
if (Int pos := haystack.indexOf("needle")) {
console.print($"Found the needle at {pos=}");
} else {
console.print("No needle in the haystack");
}
}
}
- Output:
x$ xec test Found the needle at pos=1
Elena
ELENA 6.x :
import system'routines;
import extensions;
public program()
{
var haystack := new string[]{"Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Bozo"};
new string[]{"Washington", "Bush"}.forEach::(needle)
{
var index := haystack.indexOfElement(needle);
if (index == -1)
{
console.printLine(needle," is not in haystack")
}
else
{
console.printLine(needle, " - ", index)
}
}
}
Elixir
haystack = ~w(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo)
Enum.each(~w(Bush Washington), fn needle ->
index = Enum.find_index(haystack, fn x -> x==needle end)
if index, do: (IO.puts "#{index} #{needle}"),
else: raise "#{needle} is not in haystack\n"
end)
- Output:
4 Bush ** (RuntimeError) Washington is not in haystack search.exs:5: anonymous fn/1 in :elixir_compiler_0.__FILE__/1 (elixir) lib/enum.ex:537: Enum."-each/2-lists^foreach/1-0-"/2 (elixir) lib/enum.ex:537: Enum.each/2 (elixir) lib/code.ex:316: Code.require_file/2
Emacs Lisp
(defun get-index (item list)
"Return index of first ITEM in LIST.
Display error message if ITEM is not
part of LIST."
(if (seq-position list item) ; if it's in LIST
(seq-position list item) ; return index
;; else, provide an error message
(message "%s is not an element in %s." item list)))
;; My thanks to Protesileos Stavrou (aka "Prot") for
;; key ideas for the section below, including reversing
;; the list in order to easily find the last item in it.
(defun last-position (item list)
"Return last ITEM index in LIST."
;; test if ITEM is in LIST
(if (seq-position list item) ; if it's in LIST
(progn
;; subtract the adjusted length of the list from
;; the position of ITEM in the reverse of LIST
(-
;; 1- corrects for length being 1 based, but seq-position is 0 based
(1- (length list))
;; reverse list because
;; seq-position searches from beginning of list
(seq-position (nreverse list) item)))
(message "%s is not an element in %s." item list)))
- Output:
(get-index "cat" '("cat" "cow" "dog")) 0 (#o0, #x0, ?\C-@) (get-index "horse" '("cat" "cow" "dog")) horse is not an element in (cat cow dog cat). (last-position "cat" '("cat" "cow" "dog" "cat")) 3 (#o3, #x3, ?\C-c) (last-position "horse" '("cat" "cow" "dog" "cat")) horse is not an element in (cat cow dog cat).
Erlang
Erlang lists can be accessed with the function lists:nth/2, which starts at 1 (first element). As such Erlang can be considered 1-indexed for this problem. Note that you could set the indexing to 0 by modifying the function call in pos/2.
-module(index).
-export([main/0]).
main() ->
Haystack = ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"],
Needles = ["Washington","Bush"],
lists:foreach(fun ?MODULE:print/1, [{N,pos(N, Haystack)} || N <- Needles]).
pos(Needle, Haystack) -> pos(Needle, Haystack, 1).
pos(_, [], _) -> undefined;
pos(Needle, [Needle|_], Pos) -> Pos;
pos(Needle, [_|Haystack], Pos) -> pos(Needle, Haystack, Pos+1).
print({Needle, undefined}) -> io:format("~s is not in haystack.~n",[Needle]);
print({Needle, Pos}) -> io:format("~s at position ~p.~n",[Needle,Pos]).
- Output:
Washington is not in haystack. Bush at position 5.
Euphoria
The find_all function from the standard library's search.e does nearly all the needed work here.There may be other ways to do this using Euphoria's various sequence searching functions as part of the standard library (std/search.e) and/or built into the language. The procedure can be made into a function to search with other strings, take user input and give output of the searched haystack.
include std/search.e
include std/console.e
--the string "needle" and example haystacks to test the procedure
sequence searchStr1 = "needle"
sequence haystack1 = { "needle", "needle", "noodle", "node", "need", "needle ", "needle" }
sequence haystack2 = {"spoon", "fork", "hay", "knife", "needle", "barn", "etcetera", "more hay", "needle", "a cow", "farmer", "needle", "dirt"}
sequence haystack3 = {"needle"}
sequence haystack4 = {"no", "need le s", "in", "this", "haystack"}
sequence haystack5 = {"knee", "needle", "dull", "needle"}
sequence haystack6 = {}
--search procedure with console output
procedure haystackSearch(sequence hStack)
sequence foundNeedles = find_all(searchStr1, hStack)
puts(1,"---------------------------------\r\n")
if object(foundNeedles) and length(foundNeedles) > 0 then
printf(1, "First needle found at index %d \r\n", foundNeedles[1])
if length(foundNeedles) > 1 then
printf(1, "Last needle found at index %d \r\n", foundNeedles[length(foundNeedles)] )
for i = 1 to length(foundNeedles) do
printf(1, "Needle #%d ", i)
printf(1, "was at index %d .\r\n", foundNeedles[i])
end for
else
puts(1, "There was only one needle found in this haystack. \r\n")
end if
else
puts(1, "Simulated exception - No needles found in this haystack.\r\n")
end if
end procedure
--runs the procedure on all haystacks
haystackSearch(haystack1)
haystackSearch(haystack2)
haystackSearch(haystack3)
haystackSearch(haystack4)
haystackSearch(haystack5)
haystackSearch(haystack6)
--wait for user to press a key to exit
any_key()
- Output:
--------------------------------- First needle found at index 1 Last needle found at index 7 Needle #1 was at index 1 . Needle #2 was at index 2 . Needle #3 was at index 7 . --------------------------------- First needle found at index 5 Last needle found at index 12 Needle #1 was at index 5 . Needle #2 was at index 9 . Needle #3 was at index 12 . --------------------------------- First needle found at index 1 There was only one needle found in this haystack. --------------------------------- Simulated exception - No needles found in this haystack. --------------------------------- First needle found at index 2 Last needle found at index 4 Needle #1 was at index 2 . Needle #2 was at index 4 . --------------------------------- Simulated exception - No needles found in this haystack. Press Any Key to continue...
F#
List.findIndex (fun x -> x = "bar") ["foo"; "bar"; "baz"; "bar"] // -> 1
// A System.Collections.Generic.KeyNotFoundException
// is raised, if the predicate does not evaluate to
// true for any list element.
Factor
: find-index ( seq elt -- i )
'[ _ = ] find drop [ "Not found" throw ] unless* ; inline
: find-last-index ( seq elt -- i )
'[ _ = ] find-last drop [ "Not found" throw ] unless* ; inline
( scratchpad ) { "a" "b" "c" "d" "c" } "c" find-index . 2 ( scratchpad ) { "a" "b" "c" "d" "c" } "c" find-last-index . 4
Forth
include lib/row.4th
create haystack
," Zig" ," Zag" ," Wally" ," Ronald" ," Bush" ," Krusty" ," Charlie"
," Bush" ," Boz" ," Zag" NULL ,
does>
dup >r 1 string-key row 2>r type 2r> ." is "
if r> - ." at " . else r> drop drop ." not found" then cr
;
s" Washington" haystack s" Bush" haystack
Works with any ANS Forth
Needs the FMS-SI (single inheritance) library code located here: http://soton.mpeforth.com/flag/fms/index.html
include FMS-SI.f
include FMS-SILib.f
${ Dishonest Fake Left Karl Hillary Monica Bubba Hillary Multi-Millionaire } constant haystack
: needleIndex { addr len $list | cnt -- idx }
0 to cnt $list uneach:
begin
$list each:
while
@: addr len compare 0= if cnt exit then
cnt 1+ to cnt
repeat true abort" Not found" ;
: LastIndexOf { addr len $list | cnt last-found -- idx }
0 to cnt 0 to last-found $list uneach:
begin
$list each:
while
@: addr len compare 0= if cnt to last-found then
cnt 1+ to cnt
repeat
last-found if last-found
else true abort" Not found"
then ;
s" Hillary" haystack needleIndex . \ => 4
s" Hillary" haystack LastIndexOf . \ => 7
s" Washington" haystack needleIndex . \ => aborted: Not found
Fortran
program main
implicit none
character(len=7),dimension(10) :: haystack = [ &
'Zig ',&
'Zag ',&
'Wally ',&
'Ronald ',&
'Bush ',&
'Krusty ',&
'Charlie',&
'Bush ',&
'Boz ',&
'Zag ']
call find_needle('Charlie')
call find_needle('Bush')
contains
subroutine find_needle(needle)
implicit none
character(len=*),intent(in) :: needle
integer :: i
do i=1,size(haystack)
if (needle==haystack(i)) then
write(*,'(A,I4)') trim(needle)//' found at index:',i
return
end if
end do
write(*,'(A)') 'Error: '//trim(needle)//' not found.'
end subroutine find_needle
end program main
FutureBasic
window 1, @"Search a list"
void local fn MyEnumeratorCallback( array as CFArrayRef, obj as CFTypeRef, index as NSUInteger, stp as ^BOOL, userData as ptr )
if ( fn StringIsEqual( obj, userData ) )
print obj;@" found at index ";index
*stp = YES// stop enumeration
end if
if ( index == 0 ) then print userData;@" not found"
end fn
void local fn DoIt
CFArrayRef haystack = @[@"Mike",@"Bravo",@"Tango",@"Uniform",@"Golf",
@"Tango",@"Sierra",@"November",@"Zulu",@"Delta",@"Hotel",@"Juliet"]
CFStringRef needle = @"Sierra"
NSInteger index = fn ArrayIndexOfObject( haystack, needle )
if ( index != NSNotFound )
print needle;@" found at index ";index
else
print needle;@" not found"
end if
ArrayEnumerateObjectsWithOptions( haystack, NSEnumerationReverse, @fn MyEnumeratorCallback, (ptr)@"Tango" )
end fn
fn DoIt
HandleEvents
- Output:
Sierra found at index 6 Tango found at index 5
GAP
# First position is built-in
haystack := Eratosthenes(10000);;
needle := 8999;;
Position(haystack, needle);
# 1117
LastPosition := function(L, x)
local old, new;
old := 0;
new := 0;
while new <> fail do
new := Position(L, x, old);
if new <> fail then
old := new;
fi;
od;
return old;
end;
a := Shuffle(List([1 .. 100], x -> x mod 10));
# [ 0, 2, 4, 5, 3, 1, 0, 4, 8, 8, 2, 7, 6, 3, 3, 6, 4, 4, 3, 0, 7, 1, 8, 7, 2, 4, 7, 9, 4, 9, 4, 5, 9, 9, 6, 7, 8, 2, 3,
# 5, 1, 5, 4, 2, 0, 9, 6, 1, 1, 2, 2, 0, 5, 7, 6, 8, 8, 3, 1, 9, 5, 1, 9, 6, 8, 9, 2, 0, 6, 2, 1, 6, 1, 1, 2, 5, 3, 3,
# 0, 3, 5, 7, 5, 4, 6, 8, 0, 9, 8, 3, 7, 8, 0, 4, 9, 7, 0, 6, 5, 7 ]
Position(a, 0);
# 1
LastPosition(a, 0);
# 97
See also Eratosthenes and Shuffle functions in RosettaCode.
Go
Data used by both examples below. (You can give multiple files to go run, like $ go run data.go example.go)
package main
var haystack = []string{"Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty",
"Charlie", "Bush", "Bozo", "Zag", "mouse", "hat", "cup", "deodorant",
"television", "soap", "methamphetamine", "severed cat heads", "foo",
"bar", "baz", "quux", "quuux", "quuuux", "bazola", "ztesch", "foo",
"bar", "thud", "grunt", "foo", "bar", "bletch", "foo", "bar", "fum",
"fred", "jim", "sheila", "barney", "flarp", "zxc", "spqr", ";wombat",
"shme", "foo", "bar", "baz", "bongo", "spam", "eggs", "snork", "foo",
"bar", "zot", "blarg", "wibble", "toto", "titi", "tata", "tutu", "pippo",
"pluto", "paperino", "aap", "noot", "mies", "oogle", "foogle", "boogle",
"zork", "gork", "bork", "sodium", "phosphorous", "californium",
"copernicium", "gold", "thallium", "carbon", "silver", "gold", "copper",
"helium", "sulfur"}
Linear search
package main
import "fmt"
func main() {
// first task
printSearchForward("soap")
printSearchForward("gold")
printSearchForward("fire")
// extra task
printSearchReverseMult("soap")
printSearchReverseMult("gold")
printSearchReverseMult("fire")
}
// First task solution uses panic as an exception-like mechanism, as requested
// by the task. Note however, this is not idiomatic in Go and in fact
// is considered bad practice.
func printSearchForward(s string) {
fmt.Printf("Forward search: %s: ", s)
defer func() {
if x := recover(); x != nil {
if err, ok := x.(string); ok && err == "no match" {
fmt.Println(err)
return
}
panic(x)
}
}()
fmt.Println("smallest index =", searchForwardPanic(s))
}
func searchForwardPanic(s string) int {
for i, h := range haystack {
if h == s {
return i
}
}
panic("no match")
return -1
}
// Extra task, a quirky search for multiple occurrences. This is written
// without panic, and shows more acceptable Go programming practice.
func printSearchReverseMult(s string) {
fmt.Printf("Reverse search for multiples: %s: ", s)
if i := searchReverseMult(s); i > -1 {
fmt.Println("largest index =", i)
} else {
fmt.Println("no multiple occurrence")
}
}
func searchReverseMult(s string) int {
largest := -1
for i := len(haystack) - 1; i >= 0; i-- {
switch {
case haystack[i] != s:
case largest == -1:
largest = i
default:
return largest
}
}
return -1
}
- Output:
Forward search: soap: smallest index = 15 Forward search: gold: smallest index = 77 Forward search: fire: no match Reverse search for multiples: soap: no multiple occurrence Reverse search for multiples: gold: largest index = 81 Reverse search for multiples: fire: no multiple occurrence
Map lookup
More efficient, if you're doing lots of lookups, is to build a map. This example doesn't completely conform to the task but gives the idea that you could store indexes as map values.
package main
import "fmt"
func main() {
m := map[string][]int{}
for i, needle := range haystack {
m[needle] = append(m[needle], i)
}
for _, n := range []string{"soap", "gold", "fire"} {
fmt.Println(n, m[n])
}
}
- Output:
soap [15] gold [77 81] fire []
Groovy
def haystack = ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"]
def needles = ["Washington","Bush","Wally"]
needles.each { needle ->
def index = haystack.indexOf(needle)
def lastindex = haystack.lastIndexOf(needle)
if (index < 0) {
assert lastindex < 0
println needle + " is not in haystack"
} else {
println "First index: " + index + " " + needle
println "Last index: " + lastindex + " " + needle
}
}
- Output:
Washington is not in haystack First index: 4 Bush Last index: 7 Bush First index: 2 Wally Last index: 2 Wally
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:
*Main> ((,) <*> flip elemIndex haystack) <$> needles
[("Washington",Nothing),("Bush",Just 4)]
HicEst
CHARACTER haystack='Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo.'
CHARACTER needle*10
DLG(TItle="Enter search string", Edit=needle)
n = EDIT(Text=haystack, Option=2, End, Count=needle) ! Option = word
IF( n == 0 ) THEN
WRITE(Messagebox="!") needle, "not found" ! bus not found
ELSE
first = EDIT(Text=needle, LeXicon=haystack)
WRITE(ClipBoard) "First ", needle, "found in position ", first
! First bush found in position 5
last = EDIT(Text=haystack, End, Left=needle, Count=" ") + 1
WRITE(ClipBoard) "Last ", needle, "found in position ", last
! Last bush found in position 8
ENDIF
Icon and Unicon
Taken from the public domain Icon Programming Library's lindex in lists which generates list indices for x of any type
- Output:
needle=Bush is at position 5 in haystack. needle=Bush is at last position 8 in haystack. needle=Washington is not in haystack. Run-time error 500 File haystack.icn; Line 7 program malfunction offending value: "Washington" Traceback: main(list_1 = []) runerr(500,"Washington") from line 7 in haystack.icn
Io
List has a indexOf
method which does not raise an exception on lookup failure but returns nil
therefore I extend List with a firstIndex
method that does raise an exception. I also create a lastIndex
extension that finds the last index of a matching object by iterating in reverse over the list. Note that all these methods find any object not just strings.
NotFound := Exception clone
List firstIndex := method(obj,
indexOf(obj) ifNil(NotFound raise)
)
List lastIndex := method(obj,
reverseForeach(i,v,
if(v == obj, return i)
)
NotFound raise
)
haystack := list("Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo")
list("Washington","Bush") foreach(needle,
try(
write("firstIndex(\"",needle,"\"): ")
writeln(haystack firstIndex(needle))
)catch(NotFound,
writeln(needle," is not in haystack")
)pass
try(
write("lastIndex(\"",needle,"\"): ")
writeln(haystack lastIndex(needle))
)catch(NotFound,
writeln(needle," is not in haystack")
)pass
)
- Output:
firstIndex("Washington"): Washington is not in haystack lastIndex("Washington"): Washington is not in haystack firstIndex("Bush"): 4 lastIndex("Bush"): 7
J
J has a general and optimized lookup function, i.
For example:
Haystack =: ;:'Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo'
Needles =: ;:'Washington Bush'
Haystack i. Needles NB. first positions
9 4
Haystack i: Needles NB. last positions
9 7
Note that the arguments to i.
can be anything (ie either or both may be scalars, lists, multidimensional arrays, etc). Nonmatches get a result of 1+largest valid index.
Other search primitives include:
e.
finds whether items are members of a set, returning a bitmask to select the members:
Needles e. Haystack
0 1
1 2 3 4 5 6 7 8 9 e. 2 3 5 60
0 1 1 0 1 0 0 0 0
I.
finds indices, but performs a binary search (which requires that the list being searched is sorted). This can be useful for finding non-exact matches (the index of the next value is returned for non-exact matches).
1 2 3 4 5 6 7 8 9 I. 2 3 5 60 6.66
1 2 4 9 6
(;:'eight five four nine one seven six three two') I. ;:'two three five sixty'
8 7 1 7
To format output similar to the other examples, one might write:
Haystack ;:^:_1@(] ,. [ ((<'is not in haystack')"_)`(#@[ I.@:= ])`(8!:0@])} i.) Needles
Washington is not in haystack
Bush 4
Or broken up into components and defined as a verb/function for finding the last positions:
msg=: (<'is not in haystack')"_ NB. not found message
idxmissing=: #@[ I.@:= ] NB. indices of items not found
fmtdata=: 8!:0@] NB. format atoms as boxed strings
findLastIndex=: ;:inv@(] ,. [ msg`idxmissing`fmtdata} i:)
Haystack findLastIndex Needles NB. usage
Washington is not in haystack
Bush 7
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:
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);
}
for arrays, you have to do it manually:
import java.util.Arrays;
String[] haystack = { "Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"};
for (String needle : new String[]{"Washington","Bush"}) {
int index = Arrays.binarySearch(haystack, needle);
if (index < 0)
System.out.println(needle + " is not in haystack");
else
System.out.println(index + " " + needle);
}
- Output:
Washington is not in haystack 4 Bush
JavaScript
var haystack = ['Zig', 'Zag', 'Wally', 'Ronald', 'Bush', 'Krusty', 'Charlie', 'Bush', 'Bozo']
var needles = ['Bush', 'Washington']
for (var i in needles) {
var found = false;
for (var j in haystack) {
if (haystack[j] == needles[i]) {
found = true;
break;
}
}
if (found)
print(needles[i] + " appears at index " + j + " in the haystack");
else
throw needles[i] + " does not appear in the haystack"
}
The following
:
for each (var needle in needles) {
var idx = haystack.indexOf(needle);
if (idx == -1)
throw needle + " does not appear in the haystack"
else
print(needle + " appears at index " + idx + " in the haystack");
}
// extra credit
for each (var elem in haystack) {
var first_idx = haystack.indexOf(elem);
var last_idx = haystack.lastIndexOf(elem);
if (last_idx > first_idx) {
print(elem + " last appears at index " + last_idx + " in the haystack");
break
}
}
Or, generalising enough (in ES5) to allow for varying definitions of the type of match we are looking for:
(function () {
function findIndex(fnPredicate, list) {
for (var i = 0, lng = list.length; i < lng; i++) {
if (fnPredicate(list[i])) {
return i;
}
}
return Error("not found");
};
// DEFINING A PARTICULAR TYPE OF SEARCH MATCH
function matchCaseInsensitive(s, t) {
return s.toLowerCase() === t.toLowerCase();
}
var lstHaystack = [
'Zig', 'Zag', 'Wally', 'Ronald', 'Bush',
'Krusty', 'Charlie', 'Bush', 'Bozo'
],
lstReversed = lstHaystack.slice(0).reverse(),
iLast = lstHaystack.length - 1,
lstNeedles = ['bush', 'washington'];
return {
'first': lstNeedles.map(function (s) {
return [s, findIndex(function (t) {
return matchCaseInsensitive(s, t);
},
lstHaystack)];
}),
'last': lstNeedles.map(function (s) {
var varIndex = findIndex(function (t) {
return matchCaseInsensitive(s, t);
},
lstReversed);
return [
s,
typeof varIndex === 'number' ?
iLast - varIndex : varIndex
];
})
}
})();
Output:
{
"first": [
[
"bush",
4
],
[
"washington",
"Error: not found"
]
],
"last": [
[
"bush",
7
],
[
"washington",
"Error: not found"
]
]
}
jq
The jq index origin is 0. The relevant methods for the tasks at hand are index/1 and rindex/1; indices/1 can also be used.
In the following, the output is shown after the "# =>":
["a","b","c"] | index("b")
# => 1
["a","b","c","b"] | index("b")
# => 1
["a","b","c","b"]
| index("x") // error("element not found")
# => jq: error: element not found
# Extra task - the last element of an array can be retrieved
# using `rindex/` or by using -1 as an index into the array produced by `indices/1`:
["a","b","c","b","d"] | rindex("b")
# => 3
["a","b","c","b","d"] | indices("b")[-1]
# => 3
Julia
@show findfirst(["no", "?", "yes", "maybe", "yes"], "yes")
@show indexin(["yes"], ["no", "?", "yes", "maybe", "yes"])
@show findin(["no", "?", "yes", "maybe", "yes"], ["yes"])
@show find(["no", "?", "yes", "maybe", "yes"] .== "yes")
- Output:
findfirst(["no", "?", "yes", "maybe", "yes"], "yes") = 3 indexin(["yes"], ["no", "?", "yes", "maybe", "yes"]) = [5] findin(["no", "?", "yes", "maybe", "yes"], ["yes"]) = [3, 5] find(["no", "?", "yes", "maybe", "yes"] .== "yes") = [3, 5]
K
Haystack:("Zig";"Zag";"Wally";"Ronald";"Bush";"Krusty";"Charlie";"Bush";"Bozo")
Needles:("Washington";"Bush")
{:[y _in x;(y;x _bin y);(y;"Not Found")]}[Haystack]'Needles
- Output:
(("Washington"
"Not Found")
("Bush"
4))
Additional: If more than one occurrence ("Bush"), also show position of the last occurrence. Here we use the dyadic verb _sm (string match) instead of _bin (binary search).
Haystack2: Haystack,,"Bush"
Needles2:Needles,,"Zag"
{+(x;{:[#&x;,/?(*&x;*|&x);"Not found"]}'+x _sm/:y)}[Needles2;Haystack2]
- Output:
(("Washington"
"Not found")
("Bush"
4 9)
("Zag"
1))
Kotlin
// version 1.0.6 (search_list.kt)
fun main(args: Array<String>) {
val haystack = listOf("Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Boz", "Zag")
println(haystack)
var needle = "Zag"
var index = haystack.indexOf(needle)
val index2 = haystack.lastIndexOf(needle)
println("\n'$needle' first occurs at index $index of the list")
println("'$needle' last occurs at index $index2 of the list\n")
needle = "Donald"
index = haystack.indexOf(needle)
if (index == -1) throw Exception("$needle does not occur in the list")
}
- Output:
[Zig, Zag, Wally, Ronald, Bush, Krusty, Charlie, Bush, Boz, Zag] 'Zag' first occurs at index 1 of the list 'Zag' last occurs at index 9 of the list Exception in thread "main" java.lang.Exception: Donald does not occur in the list at Search_listKt.main(search_list.kt:13)
Lang5
: haystack(*) ['rosetta 'code 'search 'a 'list 'lang5 'code] find-index ;
: find-index
2dup eq length iota swap select swap drop
length if swap drop
else drop " is not in haystack" 2 compress "" join
then ;
: ==>search apply ;
['hello 'code] 'haystack ==>search .
- Output:
[ hello is not in haystack [ 1 6 ] ]
Lasso
Lasso arrays have a findindex method which returns all matching indexes. [1]
local(haystack) = array('Zig', 'Zag', 'Wally', 'Ronald', 'Bush', 'Krusty', 'Charlie', 'Bush', 'Bozo')
#haystack->findindex('Bush')->first // 5
#haystack->findindex('Bush')->last // 8
protect => {^
handle_error => {^ error_msg ^}
fail_if(not #haystack->findindex('Washington')->first,'Washington is not in haystack.')
^}
- Output:
5 8 Washington is not in haystack.
Lingo
haystack = ["apples", "oranges", "bananas", "oranges"]
needle = "oranges"
pos = haystack.getPos(needle)
if pos then
put "needle found at index "&pos
else
put "needle not found in haystack"
end if
-- "needle found at index 2"
Lisaac
+ haystack : ARRAY[STRING];
haystack := "Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo".split;
"Washington Bush".split.foreach { needle : STRING;
haystack.has(needle).if {
haystack.first_index_of(needle).print;
' '.print;
needle.print;
'\n'.print;
} else {
needle.print;
" is not in haystack\n".print;
};
};
Logo
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
Lua
list = {"mouse", "hat", "cup", "deodorant", "television", "soap", "methamphetamine", "severed cat heads"} --contents of my desk
item = io.read()
for i,v in ipairs(list)
if v == item then print(i) end
end
M2000 Interpreter
Example based on BASIC's example, changed to find only first occurrence, and last if a second exist. We make one inventory queue which can take sane keys, and a second one with all keys in reverse order. Search works with hash table inside inventory. Normally we use Exist(inventoryA, "key") and if it is true then we get the value as Eval(inventoryA) without using second search, by temporary use of an index. We can read that index by making a variable to bind a property of COM object (the object under the inventory).
Module Checkit {
Flush ' empty stack
Inventory Queue Haystack= "foo", "bar", "baz", "quux", "quuux", "quuuux", "bazola", "ztesch", "foo", "bar", "thud", "grunt"
Append Haystack, "foo", "bar", "bletch", "foo", "bar", "fum", "fred", "jim", "sheila", "barney", "flarp", "zxc"
Append Haystack, "spqr", "wombat", "shme", "foo", "bar", "baz", "bongo", "spam", "eggs", "snork", "foo", "bar"
Append Haystack, "zot", "blarg", "wibble", "toto", "titi", "tata", "tutu", "pippo", "pluto", "paperino", "aap"
Append Haystack, "noot", "mies", "oogle", "foogle", "boogle", "zork", "gork", "bork"
\\ Inventories are objects and we have access to properties using COM model
With HayStack, "index" as index
Inventory Queue HayStackRev
N=Each(HayStack, -1, 1)
While N {
Append HayStackRev, Eval$(N, N^)
}
With HayStackRev, "index" as indexRev
Print Len(HayStack)
Print Len(HayStackRev)
local needle$
\\ Print all elements using columns
Print haystack
Repeat {
Input "Word to search for? (Leave blank to exit) ", needle$
If needle$ <> "" Then {
If Exist(haystackrev,lcase$(needle$) ) Then {
Print "Found "; CHR$(34); needle$; CHR$(34); " at index "; STR$(len(haystackrev)-indexrev,"")
If Exist(haystack,lcase$(needle$) ) Then {
if len(haystackrev)-1<>indexrev+index then {
Print "Found "; CHR$(34); needle$; CHR$(34); " at index "; STR$(Len(haystack)-index,"")
}
}
} Else Print CHR$(34); needle$; CHR$(34); " not found"
} Else Exit
} Always
}
CheckIt
Extra-Extra: Find all occurrences displaying the indexes for each one.
Module CheckThis {
Inventory Queue Haystack= "foo", "bar", "baz", "quux", "quuux", "quuuux", "bazola", "ztesch", "foo", "bar", "thud", "grunt"
Append Haystack, "foo", "bar", "bletch", "foo", "bar", "fum", "fred", "jim", "sheila", "barney", "flarp", "zxc"
Append Haystack, "spqr", "wombat", "shme", "foo", "bar", "baz", "bongo", "spam", "eggs", "snork", "foo", "bar"
Append Haystack, "zot", "blarg", "wibble", "toto", "titi", "tata", "tutu", "pippo", "pluto", "paperino", "aap"
Append Haystack, "noot", "mies", "oogle", "foogle", "boogle", "zork", "gork", "bork"
\\ Print all list
Print Haystack
\\ inventory queue can get same keys
\\ inventory use hashtable.
\\ Inventory put same keys in a linked list, so we can found easy
Do
Input "Word to search for? (Leave blank press enter to exit) ", needle$
if needle$="" then exit
n=1
s$=lcase$(needle$)
While exist(Haystack, s$, n)
\\ number, key and position (zero based convert to one based)
Print n, Eval$(HayStack!), Eval(HayStack!)+1
n++
End While
If n=1 Then Print needle$;" not found"
Always
}
CheckThis
Maple
haystack := ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"]:
occurences := ListTools:-SearchAll(needle,haystack):
try
#first occurence
printf("The first occurence is at index %d\n", occurences[1]);
#last occurence, note that StringTools:-SearchAll()retuns a list of all occurences positions
printf("The last occurence is at index %d\n", occurences[-1]);
catch :
print("Erros: Needle not found in the haystack"):
end try:
- Examples:
needle := "Washington":
"Needle not found in the haystack"
needle := "Bush":
The first occurence is at index 5 The last occurence is at index 8
Mathematica /Wolfram Language
This examples shows you the first appearance, the last appearance, and all appearances (as a list):
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]]
gives back:
2
7
{2,7}
MATLAB
Collections of strings are stored in cell arrays in MATLAB. The solution bellow will only work for a cell array of this construction:
stringCollection = {'string1','string2',...,'stringN'}
It will not work for any other construction, for example:
stringCollection = {{'string1'},{'string2'},{...},{'stringN'}}
searchCollection.m:
function index = searchCollection(list,searchItem,firstLast)
%firstLast is a string containing either 'first' or 'last'. The 'first'
%flag will cause searchCollection to return the index of the first
%instance of the item being searched. 'last' will cause
%searchCollection to return the index of the last instance of the item
%being searched.
indicies = cellfun(@(x)x==searchItem,list);
index = find(indicies,1,firstLast);
assert(~isempty(index),['The string ''' searchItem ''' does not exist in this collection of strings.']);
end
- Output:
>> list = {'a','b','c','d','e','c','f','c'};
>> searchCollection(list,'c','first')
ans =
3
>> searchCollection(list,'c','last')
ans =
8
>> searchCollection(list,'g','last')
??? Error using ==> searchCollection at 11
The string 'g' does not exist in this collection of strings.
Maxima
haystack: ["Zig","Zag","Wally","Ronald","Bush","Zig","Zag","Krusty","Charlie","Bush","Bozo"];
needle: "Zag";
findneedle(needle, haystack, [opt]):=block([idx],
idx: sublist_indices(haystack, lambda([w], w=needle)),
if emptyp(idx) then throw('notfound),
if emptyp(opt) then return(idx),
opt: first(opt),
if opt='f then first(idx) else if opt='l then last(idx) else throw('unknownmode));
- Usage:
(%i32) catch(findneedle("Zag", haystack, 'f)); (%o32) 2 (%i33) catch(findneedle("Zag", haystack, 'l)); (%o33) 7 (%i34) catch(findneedle("Washington", haystack)); (%o34) notfound (%i35) catch(findneedle("Bush", haystack, 'f)); (%o35) 5 (%i36) catch(findneedle("Zag", haystack)); (%o36) [2, 7] (%i37) catch(findneedle("Zag", haystack, 'l)); (%o37) 7
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
Nanoquery
$haystack = list()
append $haystack "Zig" "Zag" "Wally" "Ronald" "Bush" "Krusty" "Charlie"
append $haystack "Bush" "Bozo"
$needles = list()
append $needles "Washington"
append $needles "Bush"
for ($i = 0) ($i < len($needles)) ($i = $i + 1)
$needle = $needles[$i]
try
// use array lookup syntax to get the index of the needle
println $haystack[$needle] + " " + $needle
catch
println $needle + " is not in haystack"
end
end for
- Output:
Washington is not in haystack 4 Bush
NetRexx
/* 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
- Output:
Searching for "barley" in the list "Barley maize barley sorghum millet wheat rice rye barley Barley oats flax" The first occurence of "barley" is at index 3 in the list The last occurence of "barley" is at index 9 in the list The first caseless occurence of "barley" is at index 1 in the list The last caseless occurence of "barley" is at index 10 in the list Searching for "barley" in the indexed list "Barley maize barley sorghum millet wheat rice rye barley Barley oats flax" The first occurence of "barley" is at index 3 in the indexed list The last occurence of "barley" is at index 9 in the indexed list The first caseless occurence of "barley" is at index 1 in the indexed list The last caseless occurence of "barley" is at index 10 in the indexed list Searching for "quinoa" in the list "Barley maize barley sorghum millet wheat rice rye barley Barley oats flax" *** Error! "quinoa" not found in list *** Searching for "quinoa" in the indexed list "Barley maize barley sorghum millet wheat rice rye barley Barley oats flax" *** Error! "quinoa" not found in indexed list ***
Nim
let haystack = ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"]
for needle in ["Bush", "Washington"]:
let f = haystack.find(needle)
if f >= 0:
echo f, " ", needle
else:
raise newException(ValueError, needle & " not in haystack")
- Output:
4 Bush [...]/search_a_list.nim(8) search_a_list Error: unhandled exception: Washington not in haystack [ValueError]
Objeck
use Collection;
class Test {
function : Main(args : String[]) ~ Nil {
haystack := ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"];
values := CompareVector->New();
each(i : haystack) {
values->AddBack(haystack[i]->As(Compare));
};
needles := ["Washington", "Bush"];
each(i : needles) {
values->Has(needles[i]->As(Compare))->PrintLine();
};
}
}
Objective-C
NSArray *haystack = @[@"Zig",@"Zag",@"Wally",@"Ronald",@"Bush",@"Krusty",@"Charlie",@"Bush",@"Bozo"];
for (id needle in @[@"Washington",@"Bush"]) {
int index = [haystack indexOfObject:needle];
if (index == NSNotFound)
NSLog(@"%@ is not in haystack", needle);
else
NSLog(@"%i %@", index, needle);
}
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 = ()
Odin
package main
import "core:slice"
import "core:fmt"
main :: proc() {
hay_stack := []string{"Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"}
// Odin does not support exceptions.
// For conditions requiring special processing during the execution of a program it is
// encouraged to make that explicit through return values:
index, found := slice.linear_search(hay_stack, "Bush")
if found do fmt.printf("First occurence of 'Bush' at %d\n", index)
index, found = slice.linear_search(hay_stack, "Rob")
if found do fmt.printf("First occurence of 'Rob' at %d\n", index)
}
// Output:
// First occurence of 'Bush' at 4
Oforth
indexOf returns null if an object is not into a collection, not an exception.
: needleIndex(needle, haystack)
haystack indexOf(needle) dup ifNull: [ drop ExRuntime throw("Not found", needle) ] ;
[ "Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Boz" ] const: Haystack
needleIndex("Bush", Haystack) println
Haystack lastIndexOf("Bush") println
needleIndex("Washington", Haystack) println
- Output:
5 8 [1:interpreter] ExRuntime : Not found <Washington>
ooRexx
All ooRexx collections support an index method that will search for an item. For ordered collections, this will always be the first item. For unordered collections, the index returned is undetermined.
-- ordered collections always return the first hit
a = .array~of(1,2,3,4,4,5)
say a~index(4)
a2 = .array~new(5,5) -- multidimensional
a2[3,3] = 4
-- the returned index is an array of values
say a2~index(4)~makestring('line', ',')
-- Note, list indexes are assigned when an item is added and
-- are not tied to relative position
l = .list~of(1,2,3,4,4,5)
say l~index(4)
q = .queue~of(1,2,3,4,4,5)
say q~index(4)
-- directories are unordered, so it is
-- undertermined which one is returned
d = .directory~new
d["foo"] = 4
d["bar"] = 4
say d~index(4)
Oz
No such function exists for the built-in list type (the operation is quite inefficient, after all). A possible implementation:
declare
%% Lazy list of indices of Y in Xs.
fun {Indices Y Xs}
for
X in Xs
I in 1;I+1
yield:Yield
do
if Y == X then {Yield I} end
end
end
fun {Index Y Xs}
case {Indices Y Xs} of X|_ then X
else raise index(elementNotFound Y) end
end
end
Haystack = ["Zig" "Zag" "Wally" "Ronald" "Bush" "Krusty" "Charlie" "Bush" "Bozo"]
in
{Show {Index "Bush" Haystack}}
{Show {List.last {Indices "Bush" Haystack}}}
{Show {Index "Washington" Haystack}} %% throws
PARI/GP
find(v,n)={
my(i=setsearch(v,n));
if(i,
while(i>1, if(v[i-1]==n,i--))
,
error("Could not find")
);
i
};
Pascal
See Delphi
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";
}
}
- Output:
Washington is not in haystack 4 Bush
You could install a non-standard module List::MoreUtils:
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";
}
}
Alternatively, if you need to do this a lot, you could create a hash table mapping values to indices in the haystack:
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";
}
}
- Output:
Washington is not in haystack 7 Bush
Phix
constant s = {"Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Boz", "Zag"} integer r = find("Zag",s) ?r -- 2 (first) r = find("Zag",s,r+1) ?r -- 10 (next) r = find("Zag",s,r+1) ?r -- 0 (no more) r = rfind("Zag",s) ?r -- 10 (last) r = find("Zog",s) ?r -- 0 (none)
Phixmonti
"mouse" "hat" "cup" "deodorant" "television"
"soap" "methamphetamine" "severed cat heads" "cup"
pstack
stklen tolist reverse
0 tolist var t
"Enter string to search: " input var s nl
true
while
head s == if
len t swap 0 put var t
endif
tail nip len
endwhile
drop
t len not if
"String not found in list" print
else
reverse
"First index for " print s print " : " print 1 get print
len 1 > if
nl "Last index for " print s print " : " print len get print
endif
endif
drop
Other solution with syntactic sugar for list construction.
include Utilitys.pmt
0 var acum
0 var p
"Zag" var word
def search
word find var p p
enddef
( "Zig" "Zag" "Wally" "Ronald" "Bush" "Krusty" "Charlie" "Bush" "Boz" "Zag" )
dup print nl nl
search
while
p acum + var acum
( word " located in position " acum ) lprint nl
len p - p 1 + swap slice nip
search
endwhile
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";
}
- Output:
Washington is not in haystack 4 Bush
Picat
Picat has built-in functions find_first_of/2
and find_last_of/2
. They return -1 if the needle is not found, so here they are wrapped in functions that throws exceptions in this case.
And Picat is 1-based.
import util.
go =>
Haystack=["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Bush", "Charlie", "Bush", "Boz", "Zag"],
println("First 'Bush'"=search_list(Haystack,"Bush")),
println("Last 'Bush'"=search_list_last(Haystack,"Bush")),
println("All 'Bush'"=search_list_all(Haystack,"Bush")),
catch(WaldoIx=search_list(Haystack,"Waldo"),E,println(E)),
println("Waldo"=WaldoIx),
nl.
% Wrapping find_first_of/2 and find_last_of/2 with exceptions
search_list(Haystack,Needle) = Ix =>
Ix = find_first_of(Haystack,Needle),
if Ix < 0 then
throw $error(search_list(Needle),not_found)
end.
search_list_last(Haystack,Needle) = Ix =>
Ix = find_last_of(Haystack,Needle),
if Ix < 0 then
throw $error(search_list_last(Needle),not_found)
end.
% Find all indices
search_list_all(Haystack,Needle) = Ixs =>
Ixs = [Ix : {W,Ix} in zip(Haystack,1..Haystack.len), W == Needle],
if Ixs == [] then
throw $error(search_list_all(Needle),not_found)
end.
- Output:
First 'Bush' = 5 Last 'Bush' = 9 All 'Bush' = [5,7,9] error(search_list(Waldo),not_found) Waldo = _3590
PicoLisp
Note that in PicoLisp all indexes are one-based (the first element has the position '1')
(de lastIndex (Item Lst)
(- (length Lst) (index Item (reverse Lst)) -1) )
(de findNeedle (Fun Sym Lst)
(prinl Sym " " (or (Fun Sym Lst) "not found")) )
(let Lst '(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo)
(findNeedle index 'Washington Lst)
(findNeedle index 'Bush Lst)
(findNeedle lastIndex 'Bush Lst) )
- Output:
Washington not found Bush 5 Bush 8
PL/I
search: procedure () returns (fixed binary);
declare haystack (0:9) character (200) varying static initial
('apple', 'banana', 'celery', 'dumpling', 'egg', 'flour',
'grape', 'pomegranate', 'raisin', 'sugar' );
declare needle character (200) varying;
declare i fixed binary;
declare missing_needle condition;
on condition(missing_needle) begin;
put skip list ('your string ''' || needle ||
''' does not exist in the haystack.');
end;
put ('Please type a string');
get edit (needle) (L);
do i = lbound(haystack,1) to hbound(haystack,1);
if needle = haystack(i) then return (i);
end;
signal condition(missing_needle);
return (lbound(haystack,1)-1);
end search;
Plain English
To run:
Start up.
Make an example haystack.
Find "b" in the example haystack giving a count.
Destroy the example haystack.
Write "The index of ""b"" is " then the count on the console.
Wait for the escape key.
Shut down.
A needle is a string.
Some hay is some strings.
A bale is a thing with some hay.
A haystack is some bales.
To add some hay to a haystack:
Allocate memory for a bale.
Put the hay into the bale's hay.
Append the bale to the haystack.
To make an example haystack:
Add "a" to the example haystack.
Add "a" to the example haystack.
Add "b" to the example haystack.
Add "c" to the example haystack.
Add "d" to the example haystack.
\ As Plain English doesn't have exceptions, return -1 if the needle is not found.
To find a needle in a haystack giving a count:
Get a bale from the haystack.
Loop.
If the bale is nil, put -1 into the count; exit.
If the bale's hay is the needle, exit.
Put the bale's next into the bale.
Bump the count.
Repeat.
- Output:
The index of "b" is 2
PowerShell
function index($haystack,$needle) {
$index = $haystack.IndexOf($needle)
if($index -eq -1) {
Write-Warning "$needle is absent"
} else {
$index
}
}
$haystack = @("word", "phrase", "preface", "title", "house", "line", "chapter", "page", "book", "house")
index $haystack "house"
index $haystack "paragraph"
Output:
4 WARNING: paragraph is absent
PowerShell Extra credit
The -Verbose switch is available to any advanced function.
function Find-Needle
{
[CmdletBinding()]
[OutputType([int])]
Param
(
[Parameter(Mandatory=$true, Position=0)]
[string]
$Needle,
[Parameter(Mandatory=$true, Position=1)]
[string[]]
$Haystack,
[switch]
$LastIndex
)
if ($LastIndex)
{
$index = [Array]::LastIndexOf($Haystack,$Needle)
if ($index -eq -1)
{
Write-Verbose "Needle not found in Haystack"
return $index
}
if ((($Haystack | Group-Object | Where-Object Count -GT 1).Group).IndexOf($Needle) -ne -1)
{
Write-Verbose "Last needle found in Haystack at index $index"
}
else
{
Write-Verbose "Needle found in Haystack at index $index (No duplicates were found)"
}
return $index
}
else
{
$index = [Array]::IndexOf($Haystack,$Needle)
if ($index -eq -1)
{
Write-Verbose "Needle not found in Haystack"
}
else
{
Write-Verbose "Needle found in Haystack at index $index"
}
return $index
}
}
$haystack = @("word", "phrase", "preface", "title", "house", "line", "chapter", "page", "book", "house")
Find-Needle "house" $haystack
- Output:
4
Find-Needle "house" $haystack -Verbose
- Output:
VERBOSE: Needle found in Haystack at index 4 4
Find-Needle "house" $haystack -LastIndex -Verbose
- Output:
VERBOSE: Last needle found in Haystack at index 9 9
Find-Needle "title" $haystack -LastIndex -Verbose
- Output:
VERBOSE: Needle found in Haystack at index 3 (No duplicates were found) 3
Find-Needle "something" $haystack -Verbose
- Output:
VERBOSE: Needle not found in Haystack -1
Prolog
Works with SWI-Prolog
search_a_list(N1, N2) :-
L = ["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Boz", "Zag"],
write('List is :'), maplist(my_write, L), nl, nl,
( nth1(Ind1, L, N1) ->
format('~s is in position ~w~n', [N1, Ind1])
; format('~s is not present~n', [N1])),
( nth1(Ind2, L, N2) ->
format('~s is in position ~w~n', [N2, Ind2])
; format('~s is not present~n', [N2])),
( reverse_nth1(Ind3, L, N1) ->
format('~s last position is ~w~n', [N1, Ind3])
; format('~s is not present~n', [N1])).
reverse_nth1(Ind, L, N) :-
reverse(L, RL),
length(L, Len),
nth1(Ind1, RL, N),
Ind is Len - Ind1 + 1.
my_write(Name) :-
writef(' %s', [Name]).
- Output:
?- search_a_list("Zag", "Simpson"). List is : Zig Zag Wally Ronald Bush Krusty Charlie Bush Boz Zag Zag is in position 2 Simpson is not present Zag last position is 10 true.
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"
- 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:
>>> 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
>>>
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.
>>> 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"
>>>
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)
}
Example usage:
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
Racket
The function index returns the index of the the element x in the sequence xs. If the element is not found, then #f is returned.
(define (index xs y)
(for/first ([(x i) (in-indexed xs)]
#:when (equal? x y))
i))
If the last index of an element is needed, for/last is used:
(define (index-last xs y)
(for/last ([(x i) (in-indexed xs)]
#:when (equal? x y))
i))
Both index and index-last can handle any sequence such as lists, vectors, sets etc. Let us test with a linked list:
(define haystack '("Zig" "Zag" "Wally" "Ronald" "Bush" "Krusty" "Charlie" "Bush" "Bozo"))
(for/list ([needle '("Bender" "Bush")])
(index haystack needle))
(for/list ([needle '("Bender" "Bush")])
(index-last haystack needle))
- Output:
'(#f 4) '(#f 7)
Raku
(formerly Perl 6)
my @haystack = <Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo>;
for <Washington Bush> -> $needle {
say "$needle -- { @haystack.first($needle, :k) // 'not in haystack' }";
}
- Output:
Washington -- not in haystack Bush -- 4
Or, including the "extra credit" task:
my Str @haystack = <Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo>;
for <Washingston Bush> -> $needle {
my $first = @haystack.first($needle, :k);
if defined $first {
my $last = @haystack.first($needle, :k, :end);
say "$needle -- first at $first, last at $last";
}
else {
say "$needle -- not in haystack";
}
}
- Output:
Washingston -- not in haystack Bush -- first at 4, last at 7
The built-in method .first
takes a smart-matcher, and returns the first matching list element.
The :k
adverb tells it to return the key (a.k.a. list index) instead of the value of the matching element.
The :end
adverb tells it to start searching from the end of the list.
If you plan to do many searches on the same large list, you might want to build a search hash first for efficient look-up:
my @haystack = <Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo>;
my %index;
%index{.value} //= .key for @haystack.pairs;
for <Washington Bush> -> $needle {
say "$needle -- { %index{$needle} // 'not in haystack' }";
}
REBOL
REBOL [
Title: "List Indexing"
URL: http://rosettacode.org/wiki/Index_in_a_list
]
locate: func [
"Find the index of a string (needle) in string collection (haystack)."
haystack [series!] "List of values to search."
needle [string!] "String to find in value list."
/largest "Return the largest index if more than one needle."
/local i
][
i: either largest [
find/reverse tail haystack needle][find haystack needle]
either i [return index? i][
throw reform [needle "is not in haystack."]
]
]
; Note that REBOL uses 1-base lists instead of 0-based like most
; computer languages. Therefore, the index provided will be one
; higher than other results on this page.
haystack: parse "Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo" none
print "Search for first occurance:"
foreach needle ["Washington" "Bush"] [
print catch [
reform [needle "=>" locate haystack needle]
]
]
print [crlf "Search for last occurance:"]
foreach needle ["Washington" "Bush"] [
print catch [
reform [needle "=>" locate/largest haystack needle]
]
]
- Output:
Search for first occurance: Washington is not in haystack. Bush => 5 Search for last occurance: Washington is not in haystack. Bush => 8
REXX
version 1
This REXX program searches a collection of string (haystack)
that are stored in a sequential REXX array.
No counter is kept of the number of items,
but they should be numbered consecutively and can't have any gaps.
The haystack items may have any character, including blanks.
A null value isn't allowed in this method of representing values.
/*REXX program searches a collection of strings (an array of periodic table elements).*/
hay.= /*initialize the haystack collection. */
hay.1 = 'sodium'
hay.2 = 'phosphorous'
hay.3 = 'californium'
hay.4 = 'copernicium'
hay.5 = 'gold'
hay.6 = 'thallium'
hay.7 = 'carbon'
hay.8 = 'silver'
hay.9 = 'curium'
hay.10 = 'copper'
hay.11 = 'helium'
hay.12 = 'sulfur'
needle = 'gold' /*we'll be looking for the gold. */
upper needle /*in case some people capitalize stuff.*/
found=0 /*assume the needle isn't found yet. */
do j=1 while hay.j\=='' /*keep looking in the haystack. */
_=hay.j; upper _ /*make it uppercase to be safe. */
if _=needle then do; found=1 /*we've found the needle in haystack. */
leave /* ··· and stop looking, of course. */
end
end /*j*/
if found then return j /*return the haystack index number. */
else say needle "wasn't found in the haystack!"
return 0 /*indicates the needle wasn't found. */
version 2
This REXX program searches a collection of string (haystack)
that are stored in a REXX array (which may have gaps).
A safe counter is kept of the maximum (highest) index in the array,
this counter may be any sufficiently high number.
The array may be out of order (but not recommended!).
/*REXX program searches a collection of strings (an array of periodic table elements).*/
hay.0 = 1000 /*safely indicate highest item number. */
hay.200 = 'Binilnilium'
hay.98 = 'californium'
hay.6 = 'carbon'
hay.112 = 'copernicium'
hay.29 = 'copper'
hay.114 = 'flerovium'
hay.79 = 'gold'
hay.2 = 'helium'
hay.1 = 'hydrogen'
hay.82 = 'lead'
hay.116 = 'livermorium'
hay.15 = 'phosphorous'
hay.47 = 'silver'
hay.11 = 'sodium'
hay.16 = 'sulfur'
hay.81 = 'thallium'
hay.92 = 'uranium'
/* [↑] sorted by the element name. */
needle = 'gold' /*we'll be looking for the gold. */
upper needle /*in case some people capitalize. */
found=0 /*assume the needle isn't found (yet).*/
do j=1 for hay.0 /*start looking in haystack, item 1. */
_=hay.j; upper _ /*make it uppercase just to be safe. */
if _=needle then do; found=1 /*we've found the needle in haystack. */
leave /* ··· and stop looking, of course. */
end
end /*j*/
if found then return j /*return the haystack index number. */
else say needle "wasn't found in the haystack!"
return 0 /*indicates the needle wasn't found. */
version 3
This REXX program searches a collection of string (haystack)
that are stored in a REXX array.
This form uses a type of array called a sparse array (with non-numeric indexes).
One drawback of this approach is that the items can't have leading/trailing/imbedded blanks,
nor can they have special characters.
Only letters, numerals, and a few special characters are allowed: !, @, #, $, ?, and _.
This method (finding a needle in a haystack) is extremely fast as there isn't any
table look-up, the "finding" is done by REXX's own internal method of variable lookup,
and, for the most part, it based on a table hashing algorithm.
This method pre-prends an underscore (underbar) to avoid collision with any REXX
variable names. Therefore, there shouldn't be any REXX variable names (in this
program) that have a leading underscore (_).
/*REXX program searches a collection of strings (an array of periodic table elements).*/
hay.=0 /*initialize the haystack collection. */
hay._sodium = 1
hay._phosphorous = 1
hay._californium = 1
hay._copernicium = 1
hay._gold = 1
hay._thallium = 1
hay._carbon = 1
hay._silver = 1
hay._copper = 1
hay._helium = 1
hay._sulfur = 1
/*underscores (_) are used to NOT ... */
/* ... conflict with variable names. */
needle = 'gold' /*we'll be looking for the gold. */
Xneedle = '_'needle /*prefix an underscore (_) character. */
upper Xneedle /*uppercase: how REXX stores them. */
/*alternative version of above: */
/* Xneedle=translate('_'needle) */
found=hay.Xneedle /*this is it, it's found (or maybe not)*/
if found then return j /*return the haystack index number. */
else say needle "wasn't found in the haystack!"
return 0 /*indicates the needle wasn't found. */
version 4
This method uses a simple string (so haystack items can't have embedded blanks or tabs in them).
Code was added to uppercase both the haystack and the needle to make the search case insensitive.
/*REXX program searches a collection of strings (an array of periodic table elements).*/
/*───────────────names of the first 200 elements of the periodic table.─────────────*/
_= 'hydrogen helium lithium beryllium boron carbon nitrogen oxygen fluorine neon sodium'
_=_ 'magnesium aluminum silicon phosphorous sulfur chlorine argon potassium calcium'
_=_ 'scandium titanium vanadium chromium manganese iron cobalt nickel copper zinc'
_=_ 'gallium germanium arsenic selenium bromine krypton rubidium strontium yttrium'
_=_ 'zirconium niobium molybdenum technetium ruthenium rhodium palladium silver cadmium'
_=_ 'indium tin antimony tellurium iodine xenon cesium barium lanthanum cerium'
_=_ 'praseodymium neodymium promethium samarium europium gadolinium terbium dysprosium'
_=_ 'holmium erbium thulium ytterbium lutetium hafnium tantalum tungsten rhenium osmium'
_=_ 'iridium platinum gold mercury thallium lead bismuth polonium astatine radon'
_=_ 'francium radium actinium thorium protactinium uranium neptunium plutonium americium'
_=_ 'curium berkelium californium einsteinium fermium mendelevium nobelium lawrencium'
_=_ 'rutherfordium dubnium seaborgium bohrium hassium meitnerium darmstadtium'
_=_ 'roentgenium copernicium nihonium flerovium moscovium livermorium tennessine'
_=_ 'oganesson ununennium unbinilium unbiunium unbibium unbitrium unbiquadium'
_=_ 'unbipentium unbihexium unbiseptium unbioctium unbiennium untrinilium untriunium'
_=_ 'untribium untritrium untriquadium untripentium untrihexium untriseptium untrioctium'
_=_ 'untriennium unquadnilium unquadunium unquadbium unquadtrium unquadquadium'
_=_ 'unquadpentium unquadhexium unquadseptium unquadoctium unquadennium unpentnilium'
_=_ 'unpentunium unpentbium unpenttrium unpentquadium unpentpentium unpenthexium'
_=_ 'unpentseptium unpentoctium unpentennium unhexnilium unhexunium unhexbium unhextrium'
_=_ 'unhexquadium unhexpentium unhexhexium unhexseptium unhexoctium unhexennium'
_=_ 'unseptnilium unseptunium unseptbium unsepttrium unseptquadium unseptpentium'
_=_ 'unsepthexium unseptseptium unseptoctium unseptennium unoctnilium unoctunium'
_=_ 'unoctbium unocttrium unoctquadium unoctpentium unocthexium unoctseptium unoctoctium'
_=_ 'unoctennium unennilium unennunium unennbium unenntrium unennquadium unennpentium'
_=_ 'unennhexium unennseptium unennoctium unennennium binilnilium'
haystack= _ /*assign the elements ───► haystack. */
needle = 'gold' /*we'll be looking for the gold. */
upper needle haystack /*in case some people capitalize stuff.*/
idx= wordpos(needle, haystack) /*use REXX's BIF: WORDPOS */
if idx\==0 then return idx /*return the haystack index number. */
else say needle "wasn't found in the haystack!"
return 0 /*indicates the needle wasn't found. */
/*stick a fork in it, we're all done. */
Ring
haystack = ["alpha","bravo","charlie","delta","echo","foxtrot","golf",
"hotel","india","juliet","kilo","lima","mike","needle",
"november","oscar","papa","quebec","romeo","sierra","tango",
"needle","uniform","victor","whisky","x-ray","yankee","zulu"]
needle = "needle"
maxindex = len(haystack)
for index = 1 to maxindex
if needle = haystack[index] exit ok
next
if index <= maxindex
see "first found at index " + index + nl ok
for last = maxindex to 0 step -1
if needle = haystack[last] exit ok
next
if !=index see " last found at index " + last + nl
else see "not found" + nl ok
Output:
first found at index : 14 last found at index : 22
RPL
{ "Zig" "Zag" "Zig" "Wally" "Ronald" "Bush" "Krusty" "Charlie" "Bush" "Bozo" } 'HAYSTACK' STO ≪ → up ≪ HAYSTACK IF up NOT THEN REVLIST END IF SWAP POS THEN LASTARG ELSE "LOOKHAY Error: Needle not found" DOERR END ≫ ≫ 'LOOKHAY' STO
"Bush" 1 LOOKHAY "Bush" 0 LOOKHAY
- Output:
2: 6 1: 2
Ruby
haystack = %w(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo)
%w(Bush Washington).each do |needle|
if (i = haystack.index(needle))
puts "#{i} #{needle}"
else
raise "#{needle} is not in haystack\n"
end
end
- Output:
4 Bush search_a_list.rb:8:in `block in <main>': Washington is not in haystack (RuntimeError) from search_a_list.rb:4:in `each' from search_a_list.rb:4:in `<main>'
Extra credit
haystack.each do |item|
last = haystack.rindex(item)
if last > haystack.index(item)
puts "#{item} last appears at index #{last}"
break
end
end
#=> Bush last appears at index 7
or
multi_item = haystack.each_index.group_by{|idx| haystack[idx]}.select{|key, val| val.length > 1}
# multi_item is => {"Bush"=>[4, 7]}
multi_item.each do |key, val|
puts "#{key} appears at index #{val}"
end
#=> Bush appears at index [4, 7]
Rust
Rust encourages to encode possible errors in function's return type. For example, position
returns Option<usize>
, which can be None
or Some(x)
.
fn main() {
let haystack=vec!["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie",
"Bush", "Boz", "Zag"];
println!("First occurence of 'Bush' at {:?}",haystack.iter().position(|s| *s=="Bush"));
println!("Last occurence of 'Bush' at {:?}",haystack.iter().rposition(|s| *s=="Bush"));
println!("First occurence of 'Rob' at {:?}",haystack.iter().position(|s| *s=="Rob"));
}
- Output:
First occurence of 'Bush' at Some(4) Last occurence of 'Bush' at Some(7) First occurence of 'Rob' at None
Version that panics
fn main() {
let haystack=vec!["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie",
"Bush", "Boz", "Zag"];
println!("First occurence of 'Bush' at {:?}",haystack.iter().position(|s| *s=="Bush").unwrap());
println!("Last occurence of 'Bush' at {:?}",haystack.iter().rposition(|s| *s=="Bush").unwrap());
println!("First occurence of 'Rob' at {:?}",haystack.iter().position(|s| *s=="Rob").unwrap());
}
- Output:
First occurence of 'Bush' at 4 Last occurence of 'Bush' at 7 thread '<main>' panicked at 'called `Option::unwrap()` on a `None` value', /home/rustbuild/src/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libcore/option.rs:362 playpen: application terminated with error code 101
S-lang
variable haystack = ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo","Ronald"];
define find(needle)
{
variable i = where(haystack == needle);
if (length(i)) {
% print(sprintf("%s: first=%d, last=%d", needle, i[0], i[-1]));
return(i[0], i[-1]);
}
else
throw ApplicationError, "an exception";
}
($1, $2) = find("Ronald"); % returns 3, 9
($1, $2) = find("McDonald"); % throws ApplicationError, labelled "an exception"
Sather
class MAIN is
main is
haystack :ARRAY{STR} := |"Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Bozo"|;
needles :ARRAY{STR} := | "Washington", "Bush" |;
loop needle ::= needles.elt!;
index ::= haystack.index_of(needle);
if index < 0 then
#OUT + needle + " is not in the haystack\n";
else
#OUT + index + " " + needle + "\n";
end;
end;
end;
end;
Scala
The method indexOf, defined for all classes inheriting from, or having an implicit conversion to, Seq returns the index of the first element, or -1 if none exists. The method lastIndexOf does the same for the last element. Neither throws an exception, but that's easily done afterwards.
However, a simple implementation, not using those or similar methods might be written like this:
def findNeedles(needle: String, haystack: Seq[String]) = haystack.zipWithIndex.filter(_._1 == needle).map(_._2)
def firstNeedle(needle: String, haystack: Seq[String]) = findNeedles(needle, haystack).head
def lastNeedle(needle: String, haystack: Seq[String]) = findNeedles(needle, haystack).last
It does raise an exception if there's no needle.
Scheme
(define haystack
'("Zig" "Zag" "Wally" "Ronald" "Bush" "Krusty" "Charlie" "Bush" "Bozo"))
(define index-of
(lambda (needle hackstack)
(let ((tail (member needle haystack)))
(if tail
(- (length haystack) (length tail))
(throw 'needle-missing)))))
(define last-index-of
(lambda (needle hackstack)
(let ((tail (member needle (reverse haystack))))
(if tail
(- (length tail) 1)
(throw 'needle-missing)))))
- Output:
(index-of "Bush" haystack) 4 (last-index-of "Bush" haystack) 7
SenseTalk
put ("apple", "banana", "cranberry" ,"durian", "eggplant", "grape", "banana", "appl", "blackberry") into fruitList
put findInList(fruitList,"banana") // 2
put findInList(fruitList,"banana", true) // 7
put findInList(fruitList,"tomato") // throws an exception
function findInList paramList, paramItem, findLast
set temp to every offset of paramItem within paramList
if (number of items in temp = 0)
Throw InvalidSearch, "Item not found in list"
end if
if findLast
return last item of temp
else
return first item of temp
end if
end findInList
Note: Sensetalk indexes from 1
Sidef
var haystack = %w(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo);
%w(Bush Washington).each { |needle|
var i = haystack.first_index{|item| item == needle};
if (i >= 0) {
say "#{i} #{needle}";
} else {
die "#{needle} is not in haystack";
}
}
- Output:
4 Bush Washington is not in haystack at find.sf line 9.
Extra credit:
var haystack = %w(Zig Zag Wally Ronald Bush Krusty Charlie Bush Bozo);
say haystack.last_index{|item| item == "Bush"};
- Output:
7
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]]].
Smalltalk
Notice: Smalltalk indexes start at 1.
| haystack |
haystack := 'Zig,Zag,Wally,Ronald,Bush,Krusty,Charlie,Bush,Bozo' subStrings: $,.
{ 'Washington' . 'Bush' } do: [:word |
|t|
((t := haystack indexOf: word) = 0)
ifTrue: [ ('%1 is not in the haystack' % { word }) displayNl ]
ifFalse: [
|l|
('%1 is at index %2' % { word . t }) displayNl.
l := ( (haystack size) - (haystack reverse indexOf: word) + 1 ).
( t = l ) ifFalse: [
('last occurence of %1 is at index %2' % { word . l }) displayNl ]
]
].
the above example did not raise an exception; the following does (a handler has been added to proceed for more search words):
Notice: the code below uses the ST/X embedded-expression-string extension.
| haystack |
haystack := 'Zig,Zag,Wally,Ronald,Bush,Krusty,Charlie,Bush,Bozo' subStrings: $,.
[
{ 'Washington' . 'Bush' . 'Ronald' } do: [:word |
|firstIdx lastIdx|
firstIdx := haystack
indexOf:word
ifAbsent:[
ProceedableError raiseRequestWith:word errorString:'not found'.
0
].
firstIdx = 0 ifFalse:[
(lastIdx := haystack lastIndexOf:word) = firstIdx
ifTrue:[ e'the first index of {word} is {firstIdx}' printCR ]
ifFalse:[ e'the last index of {word} is {lastIdx}' printCR ]]
]
] on:Error do:[:ex |
e'{ex description} exception raised for: {ex parameter}' printCR.
'but I don''t care and proceed...' printCR.
ex proceed.
]
- Output:
not found exception raised for: Washington but I don't care and proceed... the last index of Bush is 8 the first index of Ronald is 4
Standard ML
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"];
Swift
let haystack = ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"]
for needle in ["Washington","Bush"] {
if let index = haystack.indexOf(needle) {
print("\(index) \(needle)")
} else {
print("\(needle) is not in haystack")
}
}
let haystack = ["Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"]
for needle in ["Washington","Bush"] {
if let index = find(haystack, needle) {
println("\(index) \(needle)")
} else {
println("\(needle) is not in haystack")
}
}
The second task:
// the second part can be done several ways, but extending any Array of Comparable objects is the most generic approach
extension Array where Element : Comparable {
func lastIndexMatching(needle:Element) -> Int? {
for i in stride(from: count-1, through: 0, by: -1) {
if self[i] == needle {
return i
}
}
return nil
}
}
for needle in ["Washington","Bush"] {
if let index = haystack.lastIndexMatching(needle) {
print("\(index) \(needle)")
} else {
print("\(needle) is not in haystack")
}
}
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"
}
}
Extra credit:
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]"
}
}
TorqueScript
--Elm 03:38, 18 June 2012 (UTC)
Find multiple needles in a haystack:
function findIn(%haystack,%needles)
{
%hc = getWordCount(%haystack);
%nc = getWordCount(%needles);
for(%i=0;%i<%nc;%i++)
{
%nword = getWord(%needles,%i);
%index[%nword] = -1;
}
for(%i=0;%i<%hc;%i++)
{
%hword = getWord(%haystack,%i);
for(%j=0;%j<%nc;%j++)
{
%nword = getWord(%needles,%j);
if(%hword $= %nword)
{
%index[%nword] = %i;
}
}
}
for(%i=0;%i<%nc;%i++)
{
%nword = getWord(%needles,%i);
%string = %string SPC %nword@"_"@%index[%nword];
%string = trim(%string);
}
return %string;
}
How to use it:
echo(findIn("Hello world, you are quite sunny today.","quite hello somethingelse"));
returns:
=> "quite_4 hello_0 somethingelse_-1"
TUSCRIPT
$$ MODE TUSCRIPT
SET haystack="Zig'Zag'Wally'Ronald'Bush'Krusty'Charlie'Bush'Bozo"
PRINT "haystack=",haystack
LOOP needle="Washington'Bush'Wally"
SET table =QUOTES (needle)
BUILD S_TABLE needle = table
IF (haystack.ct.needle) THEN
BUILD R_TABLE needle = table
SET position=FILTER_INDEX(haystack,needle,-)
RELEASE R_TABLE needle
PRINT "haystack contains ", needle, " on position(s): ",position
ELSE
PRINT "haystack not contains ",needle
ENDIF
RELEASE S_TABLE needle
ENDLOOP
- Output:
haystack=Zig'Zag'Wally'Ronald'Bush'Krusty'Charlie'Bush'Bozo haystack not contains Washington haystack contains Bush on position(s): 5'8 haystack contains Wally on position(s): 3
UNIX Shell
if [ $1 ];then
haystack="Zip Zag Wally Ronald Bush Krusty Charlie Bush Bozo"
index=$(echo $haystack|tr " " "\n"|grep -in "^$1$")
if [ $? = 0 ];then
quantity_of_hits=$(echo $index|tr " " "\n"|wc -l|tr -d " ")
first_index=$(echo $index|cut -f 1 -d ":")
if [ $quantity_of_hits = 1 ];then
echo The sole index for $1 is: $first_index
else
echo The smallest index for $1 is: $first_index
greatest_index=$(echo $index|tr " " "\n"|tail -1|cut -f 1 -d ":")
echo "The greatest index for $1 is: $greatest_index";fi
else echo $1 is absent from haystatck.;fi
else echo Must provide string to find in haystack.;fi
- Output:
./needle_haystack clay ---> clay is absent from haystatck. ./needle_haystack charlie ---> The sole index for charlie is: 7 ./needle_haystack bush ---> The smallest index for bush is: 5 The greatest index for bush is: 8
Ursala
The indices
function takes a pair 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.
#import std
indices = ||<'missing'>!% ~&nSihzXB+ ~&lrmPE~|^|/~& num
The explanation is somewhat longer than the program.
- The
^|
operator takes a right operand consisting of a pair of functions , and returns a function that takes a pair to the result . - An expression of the form
h/f g
whereh
is a function taking a pair, is equivalent toh(f,g)
. - The
~&
operator represents the identity function. - The expression
^|/~& num
applied to an argument therefore evaluates tonum
- The
num
function takes any list and transforms it to a list of pairs . - The left operand to the
^|
operator, if any, is composed with the function constructed from the right. In this case, the left operand is~&lrmPE~|
- The
~|
operator takes a predicate as its left operand and returns a function that operates on a pair , where is expected to be a list. The resulting function is evaluated by pairing with each item of , applying the predicate to each pair, and making a list of the items of for which the predicate holds on the pair. - The predicate in this case is
~&lrmPE
, which will be passed an input of the form for the -th item in terms of the notation above. - The expression
~&lrmPE
has a root operatorE
, which tests for equality, a left operandl
, which extracts the left side of its argument, and a right operand ofrmP
, which is the reverse composition (P
) of the right side extraction (r
) operator, followed by a further right side extraction expressed more idiomatically asm
when the argument in question represents some type of key-value pair. - The predicate therefore compares the left side of , which is , to the right of the right, which is
- The result from
~&lrmPE~|
will be a list of pairs of the form , for indices at which appears in the list. - This result is passed to the function
~&nSihzXB
, which consists of subexpressionsnS
andihzXB
that operate sequentially. - The
nS
subexpression makes a list of the left sides of all items of a list of key-value pairs, in this case constructing a list of indices from the input, and passing it to the subexpressionihzXB
. - The subexpression
ihzXB
has a left subexpressioni
, a right subexpressionhzX
and a rootB
. - The
B
(mnemonic for "both") operator causes the left subexpression to be applied to the argument as a test, and if the result is non-empty, returns the result of applying the right. - The left subexpression
i
represents the identity function, and tests whether the argument list is non-empty. - If the list is non-empty, the expression
hzX
constructs the pair (X
) of the head (h
) and the last item (z
) of the list given in the argument. - The disjunction operator
||
used in an expression of the form||u v
with functionsu
andv
constructs a function that appliesv
to the argument, returns that result if non-empty, but otherwise returns the the result of applyingv
to the argument. - The expression
<'missing'>
is a list of strings representing the diagnostic message to be returned in the event of an empty list (corresponding to the not being present). - The constant operator (
!
) is used because the message is not data-dependent. - The exception throwing operator (
%
) compels the result of its operand to be returned in a way that bypasses the usual flow of control.
Test program:
#cast %nW
test = indices/'bar' <'foo','bar','baz','bar'>
- Output:
(1,3)
VBA
Function IsInArray(stringToBeFound As Variant, arr As Variant, _
Optional start As Integer = 1, Optional reverse As Boolean = False) As Long
'Adapted from https://stackoverflow.com/questions/12414168/use-of-custom-data-types-in-vba
Dim i As Long, lo As Long, hi As Long, stp As Long
' default return value if value not found in array
IsInArray = -1
If reverse Then
lo = UBound(arr): hi = start: stp = -1
Else
lo = start: hi = UBound(arr): stp = 1
End If
For i = lo To hi Step stp 'start in stead of LBound(arr)
If StrComp(stringToBeFound, arr(i), vbTextCompare) = 0 Then
IsInArray = i
Exit For
End If
Next i
End Function
Public Sub search_a_list()
Dim haystack() As Variant, needles() As Variant
haystack = [{"Zig","Zag","Wally","Ronald","Bush","Krusty","Charlie","Bush","Bozo"}]
needles = [{"Washington","Bush"}]
For i = 1 To 2
If IsInArray(needles(i), haystack) = -1 Then
Debug.Print needles(i); " not found in haystack."
Else
Debug.Print needles(i); " is at position "; CStr(IsInArray(needles(i), haystack)); ".";
Debug.Print " And last position is ";
Debug.Print CStr(IsInArray(needles(i), haystack, 1, True)); "."
End If
Next i
End Sub
- Output:
Washington not found in haystack. Bush is at position 5. And last position is 8.
VBScript
Shamelessly derived from the BASIC version.
data = "foo,bar,baz,quux,quuux,quuuux,bazola,ztesch,foo,bar,thud,grunt," &_
"foo,bar,bletch,foo,bar,fum,fred,jim,sheila,barney,flarp,zxc," &_
"spqr,wombat,shme,foo,bar,baz,bongo,spam,eggs,snork,foo,bar," &_
"zot,blarg,wibble,toto,titi,tata,tutu,pippo,pluto,paperino,aap," &_
"noot,mies,oogle,foogle,boogle,zork,gork,bork"
haystack = Split(data,",")
Do
WScript.StdOut.Write "Word to search for? (Leave blank to exit) "
needle = WScript.StdIn.ReadLine
If needle <> "" Then
found = 0
For i = 0 To UBound(haystack)
If UCase(haystack(i)) = UCase(needle) Then
found = 1
WScript.StdOut.Write "Found " & Chr(34) & needle & Chr(34) & " at index " & i
WScript.StdOut.WriteLine
End If
Next
If found < 1 Then
WScript.StdOut.Write Chr(34) & needle & Chr(34) & " not found."
WScript.StdOut.WriteLine
End If
Else
Exit do
End If
Loop
- Output:
F:\VBScript>cscript /nologo search_a_list.vbs Word to search for? (Leave blank to exit) foo Found "foo" at index 0 Found "foo" at index 8 Found "foo" at index 12 Found "foo" at index 15 Found "foo" at index 27 Found "foo" at index 34 Word to search for? (Leave blank to exit) bar Found "bar" at index 1 Found "bar" at index 9 Found "bar" at index 13 Found "bar" at index 16 Found "bar" at index 28 Found "bar" at index 35 Word to search for? (Leave blank to exit) fff "fff" not found. Word to search for? (Leave blank to exit) F:\VBScript>
V (Vlang)
const (
haystacks = ["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Bozo"]
needles = ["Bush", "washington", "Wally"]
)
fn main() {
mut list, mut index, mut count, mut missing := "", "", "", ""
for nee in needles {
for idx, hay in haystacks {
if nee == hay {
count = "${haystacks.str().count(nee)}"
if list.contains(nee) {
index += ", ${idx}"
list = "Found: ${nee}; Index: ${index}; Count: ${count}\n"
}
else {
index = "${idx}"
list += "Found: ${nee}; Index: ${index}; Count: ${count}\n"
}
}
}
if nee !in haystacks && !missing.contains(nee) {missing += "Missing: ${nee}\n"}
}
list += missing
println(list.all_before_last('\n'))
}
- Output:
Found: Bush; Index: 4, 7; Count: 2 Found: Wally; Index: 2; Count: 1 Missing: washington
Wart
Wart uses the function pos
to search a list for an element.
Here's how it's implemented:
def (pos x (seq | (head ... tail)) n)
default n :to 0
if seq
if (head = x)
n
(pos x tail n+1)
- Usage:
pos 3 '(1 2 3 4 5) => 2 pos 24 '(1 2 3 4 5) => nil
Wren
import "./seq" for Lst
var find = Fn.new { |haystack, needle|
var res = Lst.indicesOf(haystack, needle)
if (!res[0]) Fiber.abort("Needle not found in haystack.")
System.print("The needle occurs %(res[1]) time(s) in the haystack.")
if (res[1] == 1) {
System.print("It occurs at index %(res[2][0])")
} else {
System.print("It first occurs at index %(res[2][0])")
System.print("It last occurs at index %(res[2][-1])")
}
System.print()
}
var haystack = ["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Boz", "Zag"]
System.print("The haystack is:\n%(haystack)\n")
var needles = ["Wally", "Bush", "Zag", "George"]
for (needle in needles) {
System.print("The needle is %(needle).")
find.call(haystack, needle)
}
- Output:
The haystack is: [Zig, Zag, Wally, Ronald, Bush, Krusty, Charlie, Bush, Boz, Zag] The needle is Wally. The needle occurs 1 time(s) in the haystack. It occurs at index 2 The needle is Bush. The needle occurs 2 time(s) in the haystack. It first occurs at index 4 It last occurs at index 7 The needle is Zag. The needle occurs 2 time(s) in the haystack. It first occurs at index 1 It last occurs at index 9 The needle is George. Needle not found in haystack. [./search_list line 5] in new(_) block argument [./search_list line 21] in (script)
XPL0
\Based on C example:
include c:\cxpl\stdlib; \provides StrCmp routine, etc.
int Haystack; \('int' is used instead of 'char' for 2D array)
func Search(Str, First); \Return first (or last) index for string in haystack
char Str; int First;
int I, SI;
[I:= 0; SI:= 0;
repeat if StrCmp(Str, Haystack(I)) = 0 then
[if First then return I;
SI:= I; \save index
];
I:= I+1;
until Haystack(I) = 0;
return SI;
];
[Haystack:= ["Zig", "Zag", "Wally", "Ronald", "Bush",
"Krusty", "Charlie", "Bush", "Boz", "Zag", 0];
Text(0, "Bush is at "); IntOut(0, Search("Bush", true)); CrLf(0);
if Search("Washington", true) = 0 then
Text(0, "Washington is not in the haystack^M^J");
Text(0, "First index for Zag: "); IntOut(0, Search("Zag", true)); CrLf(0);
Text(0, "Last index for Zag: "); IntOut(0, Search("Zag", false)); CrLf(0);
]
- Output:
Bush is at 4 Washington is not in the haystack First index for Zag: 1 Last index for Zag: 9
Yorick
haystack = ["Zig", "Zag", "Wally", "Ronald", "Bush", "Krusty", "Charlie", "Bush", "Bozo"];
needles = ["Bush", "Washington"];
for(i = 1; i <= numberof(needles); i++) {
w = where(haystack == needles(i));
if(!numberof(w))
error, "Needle "+needles(i)+" not found";
write, format="Needle %s appears first at index %d\n", needles(i), w(1);
if(numberof(w) > 1)
write, format="Needle %s appears last at index %d\n", needles(i), w(0);
}
zkl
L("Krusty","Charlie","Bozo","Bozo").index("Charlie") //--> 1
L("Krusty","Charlie","Bozo","Bozo").index("fred") //--> throws index error
Find last needle:
haystack:=L("Krusty","Charlie","Bozo","Bozo");
haystack.filterNs('==("Bozo"))[-1]; // -->3, indexError if not found
haystack.len() - 1 - haystack.reverse().index("Bozo"); // or this
Use a bit bucket of ASCIIZ strings
haystack:=Data(0,String,"Krusty","Charlie","Bozo","Bozo");
if((n:=haystack.findString("Charlie")) != Void) n else throw(Exception.IndexError);
//-->7
- Programming Tasks
- Text processing
- 11l
- ACL2
- Acornsoft Lisp
- Action!
- ActionScript
- Ada
- Aime
- ALGOL 68
- Arturo
- AutoHotkey
- AWK
- BASIC
- BASIC256
- BBC BASIC
- IS-BASIC
- FreeBASIC
- Gambas
- Liberty BASIC
- PowerBASIC
- PureBasic
- Run BASIC
- Yabasic
- Batch File
- BQN
- Bracmat
- Burlesque
- C
- C sharp
- C++
- Ceylon
- Clojure
- CLU
- COBOL
- Common Lisp
- D
- Delphi
- DWScript
- E
- EasyLang
- Ecstasy
- Elena
- Elixir
- Emacs Lisp
- Erlang
- Euphoria
- F Sharp
- Factor
- Forth
- Fortran
- FutureBasic
- GAP
- Go
- Groovy
- Haskell
- HicEst
- Icon
- Unicon
- Icon Programming Library
- Io
- J
- Java
- JavaScript
- Jq
- Julia
- K
- Kotlin
- Lang5
- Lasso
- Lingo
- Lisaac
- Logo
- Lua
- M2000 Interpreter
- Maple
- Mathematica
- Wolfram Language
- MATLAB
- Maxima
- MAXScript
- Nanoquery
- NetRexx
- Nim
- Objeck
- Objective-C
- OCaml
- Odin
- Oforth
- OoRexx
- Oz
- PARI/GP
- Pascal
- Perl
- Phix
- Phix/basics
- Phixmonti
- PHP
- Picat
- PicoLisp
- PL/I
- Plain English
- PowerShell
- Prolog
- Python
- R
- Racket
- Raku
- REBOL
- REXX
- Ring
- RPL
- Ruby
- Rust
- S-lang
- Sather
- Scala
- Scheme
- SenseTalk
- Sidef
- Slate
- Smalltalk
- Standard ML
- Swift
- Tcl
- TorqueScript
- TUSCRIPT
- UNIX Shell
- Ursala
- VBA
- VBScript
- V (Vlang)
- Wart
- Wren
- Wren-seq
- XPL0
- Yorick
- Zkl
- Pages with too many expensive parser function calls