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
xare 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
xare 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 0Vector – general list: type error
Where
xis a vector andyis 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
xare 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") 3yis enlisted for matching.q)("st";"ring";"s")?"s" / not found 3 q)("st";"ring";(),"s")?"s" / found 2So there is no way to match an atom item in
x. - list ? list
-
Items of
xare matched to items ofy.Tables are lists.q)("cow";"sheep";"cat";"dog")?("cat";"cow") 2 0q)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")?qbfAnswer
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 3In the fourth example, the first item of
xis an atom, so items ofxare matched to items ofy– in this case, atoms. Only the"a"matches an item ofx. -
Write a lambda or composition
fpthat works like Find but matches strings using q’s limited pattern matching instead of Match, so thatq)fp[sss;"sh*"] 0 3 7Answer
fp:('[where;like]) / {where x like y}