Searching
Find with vectors is intuitive. With general lists, not so much.
Find
Where x
is a list
x?y / finds the first occurrences of y in x
y
is not found, the index returned is count[x]
.
q)"bad beef"?"bread"
0 8 5 1 2
Simple cases
Where x
and y
are both vectors, or both general lists, atoms are matched with atoms, or items with items.
q)0 1 1 2 3 5 8 13 21 34 55? 8 2 13 -1
6 3 7 11
q)("pain";"viande";"legumes")?("pain";"perdu")
0 3
x
is a vector and y
is a list, Find is right-atomic.
q)`the`glory`that`was`rome?(`rome`glory;(`was`that;`glory);`really)
4 1
(3 2;1)
5
x
is a general list and y
is a vector, Find looks for y
as an item of x
.
q)("cow";"sheep";42;`skidoo)?"sheep"
1
Matching rules
The matching rules apply to all kinds of lists, not just vectors and lists of vectors. For general lists, the results can be counter-intuitive.
The first items of the arguments determine what gets matched.
A general list can have an atom as its first item.
Matching rules according to the first items of x
and y
:
- atom ? atom
-
Items of
x
are matched to items ofy
.q)0 1 1 2 3 5 8 13 21 34?8 7 1 1 / vector - vector 6 10 1 1 q)("b";"string";"x";"i")?("x";"string") / general list - general list 2 1 q)("b";"string";"x";"i")?"x" / general list - atom 2 q)("b";"string";"x";"i")?"string" / general list - vector 4 4 4 3 4 4
- atom ? list
-
Items of
x
are matched to atoms ofy
. Find is right-atomic.q)"strings"?("st";"ring") / vector - general 0 1 2 3 4 5 q)("s";"t";"ring";"s")?("st";"rings") / general - general 0 1 4 4 4 4 0
Vector – general list: type error
Where
x
is a vector andy
is a general list whose first item is an atom, or that contains such a general list, Find signals a type error.q)"bad beef"?("bee";("bead";"b");"abed") 0 5 5 (0 5 1 2;0) 1 0 5 2 q)"bad beef"?("bee";("b";"bead");"abed") 'type [0] "bad beef"?("bee";("b";"bead");"abed") ^
- list ? atom
-
Items of
x
are matched to the whole ofy
; i.e.x~\:(),y
.Notice that an atomq)("st";"ring";"s")?"ring" 1 q)("st";"ring";"s")?("s";"ring";"st") 3
y
is enlisted for matching.q)("st";"ring";"s")?"s" / not found 3 q)("st";"ring";(),"s")?"s" / found 2
So there is no way to match an atom item in
x
. - list ? list
-
Items of
x
are matched to items ofy
.Tables are lists.q)("cow";"sheep";"cat";"dog")?("cat";"cow") 2 0
q)t name age eyes hair -------------------- tom 31 blue fair raja 33 brown black emil 27 green brown xin 33 brown black q)u name age eyes hair -------------------- xin 33 brown black raja 33 brown black ken 35 blue fair q)t?u 3 1 4
Summary:
x[0] | y[0] | items of x matched to
-----|------|----------------------
atom | atom | items of y
atom | list | atoms of y
list | atom | (),y
list | list | items of y
String searches
The Find operator can locate entire strings:
q)("cow";"sheep";"cat")?"sheep"
1
q)("cow";"sheep";"cat")?("sheep";"dog")
1 3
q)"she looked sheepish"?"she"
0 1 2
ss
finds substrings within a longer string:
q)"she looked sheepish"ss"she"
0 11
q)"sea shells"ss"s??"
0 4
like
keyword reports whether one or more strings x
match a pattern y
.
q)("she";"sells";"sea";"shells")like"sh*"
1001b
q)"shell"like"sh*"
1b
Exercises
No peeking.
Attempt each exercise before looking at its answer.
The exercises clarify your thinking. Reading answers does not.
qbf:"thequickbrownfoxjumpsoverthelazydog"
sss:string`she`sells`sea`shells`by`the`sea`shore
-
Predict the results of
0 1 1 2 3 5 8 13 21 34?55 5 1 sss?("sea";"saw") sss?"shells"
Answer
q)0 1 1 2 3 5 8 13 21 34?55 5 1 10 5 1 q)sss?("sea";"saw") 2 8 q)sss?"shells" 3
-
Predict the results of
count each qbf?("the";("strings";"of");"saturn") count each qbf?("a";("ring";"of");"saturn") ("a";("ring";"of");"saturn")?qbf
Answer
The third example signals a type error because the nested-list right argument contains an atom item.q)qbf?("the";("strings";"of");"saturn") 0 1 2 (20 0 9 5 12 34 20;10 13) 20 29 0 4 9 12 q)count each qbf?("the";("strings";"of");"saturn") 3 2 6 q)count each qbf?("a";("ring";"of");"saturn") 'type [0] count each qbf?("a";("ring";"of");"saturn") q)("a";("ring";"of");"saturn")?qbf 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 0 3 3 3 3 3
In the fourth example, the first item of
x
is an atom, so items ofx
are matched to items ofy
– in this case, atoms. Only the"a"
matches an item ofx
. -
Write a lambda or composition
fp
that works like Find but matches strings using q’s limited pattern matching instead of Match, so thatq)fp[sss;"sh*"] 0 3 7
Answer
fp:('[where;like]) / {where x like y}