Reputation: 23
If I have a sequence of values, how would I find the index of an element based on a predicate function? For example, if I had the following seq:
let values = @["pie", "cake", "ice cream"]
How would I find the index of the first element with four characters? I know of find
, but it seems to only find index by equality, and does not allow passing a predicate. I could implement this myself but it feels as if it should be be in the standard library if find
is.
Upvotes: 2
Views: 1147
Reputation: 21363
A simple solution would be to use map
from sequtils
to map the predicate over the input sequence, and then to use find
to get the index of the first true
value in the result. This returns -1 when no element of the sequence satisfies the predicate:
import sequtils
proc isLen4(s: string): bool =
len(s) == 4
echo map(@["pie", "cake", "ice cream"], isLen4).find(true) #--> 1
This works, but is bad for large sequences since map
processes the entire sequence. Thus even when the first element satisfies the predicate the entire sequence is processed. It would be better to just write a findIf
procedure that returns the current index when the predicate is satisfied instead of continuing to process the rest of the input:
proc findIf[T](s: seq[T], pred: proc(x: T): bool): int =
result = -1 # return -1 if no items satisfy the predicate
for i, x in s:
if pred(x):
result = i
break
echo @["pie", "cake", "ice cream"].findIf(isLen4) #--> 1
Upvotes: 4