Strings¶
Character vectors are known informally in q as strings.
For phrases relating to character matrixes and nested lists, see Text.
Alphabetic comparison¶
q)"a"<"b"
1b
q)"a">"b"
0b
q)"i"$";"
59
q){enlist[" ",x],x,'" *"x<\:x}PUN,{upper[x],x}.Q.a
" ,;:.!?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
", *** *****************************************************"
"; *****************************************************"
": * *****************************************************"
". ** *****************************************************"
"!**** *****************************************************"
"? ****************************************************"
"A ***************************************************"
"B **************************************************"
"C *************************************************"
"D ************************************************"
"E ***********************************************"
"F **********************************************"
"G *********************************************"
"H ********************************************"
"I *******************************************"
"J ******************************************"
"K *****************************************"
"L ****************************************"
"M ***************************************"
"N **************************************"
"O *************************************"
..
Blanks¶
Remove blanks¶
q)x:" bcde bc"
q)x where x<>" "
"bcdebc"
q)x except " "
"bcdebc"
Remove trailing blanks¶
q)x:"trailing blanks "
q)(neg sum mins reverse " "=x)_ x
"trailing blanks"
sum
and mins
must evaluate the whole vector. But Find terminates with the first hit.
q)(neg reverse[x=" "]?0b)_ x
"trailing blanks"
Or.
q)x where reverse maxs reverse x<>" "
"trailing blanks"
Remove leading blanks¶
q)x:" phrase 267 "
q)x where maxs x<>" "
"phrase 267 "
Remove leading and trailing blanks¶
q)x:" abcd e fg "
q)a:not x=" "
q)a
0001111010011000b
q)(maxs a) and reverse maxs reverse a
0001111111111000b
q)where (maxs a) and reverse maxs reverse a
3 4 5 6 7 8 9 10 11 12
q)x where maxs[a]and reverse maxs reverse a:x<>" "
"abcd e fg"
Or.
q)x where(and)over 0 1 reverse/'maxs each 1 reverse\x<>" "
"abcd e fg"
Or Find and Drop rather than maxs
and Index.
q)x{y _ x}/1 -1*(" "=1 reverse\x)?'0b
"abcd e fg"
Collapse multiple blanks¶
379, 426
q)/ test cases
q)show c:{(x;" ",x," ";" ",x," ")}each("foo";"foo bar";"foo bar")
"foo" " foo " " foo "
"foo bar" " foo bar " " foo bar "
"foo bar" " foo bar " " foo bar "
q)/ correct results
q)show r:{(x 0;" ",x[1]," ";" ",x[2]," ")}each 3 3#("foo";"foo bar")where 3 6
"foo" " foo " " foo "
"foo bar" " foo bar " " foo bar "
"foo bar" " foo bar " " foo bar "
q)cmb:{x where 1b,1_(or)prior" "<>x}
q)r~''cmb''[c]
111b
111b
111b
Alternative algorithm works on trimmed strings.
q)x:"a b c d"
q)x where 1 rotate(or)prior" "<>x
"a b c d"
Move blanks to end¶
q)x:"sign if i cant"
q)x[iasc x=" "]
"significant "
q)be:{x[iasc x=" "]}
q)y:("yo ho ho";"and a bottle";"of rum")
q)be each y
"yohoho "
"andabottle "
"ofrum "
Justify right¶
q)x:"trailing blanks "
q)neg[(reverse[x]=" ")?0b]rotate x
" trailing blanks"
q)rj:{neg[(reverse[x]=" ")?0b]rotate x}
q)rj each ("a ";"bc ";"d e ";"fg h ";"ij kl ";"mnopqr")
" a"
" bc"
" d e"
" fg h"
" ij kl"
"mnopqr"
Center text x in line of width y¶
q)x:"1234567890"
q)y:16
q)y#x,y#" "
"1234567890 "
q)y-count x
6
q)floor(y-count x)%2
3
q)neg[floor(y-count x)%2]rotate y#x,y#" "
" 1234567890 "
Or.
q)@[y#" ";(floor(y-count x)%2)+tc x;:;x]
" 1234567890 "
Above should be faster but breaks where y<count x
.
Insert spaces in text¶
q)x:"wider"
q)-1_raze x,'" "
"w i d e r"
Or.
q)c:-1+2*count x
q)@[c#" ";where c#1 0;:;x]
"w i d e r"
Conditional text¶
q)x:0
q)raze((not x)#'"in"),"correct"
"incorrect"
q)x:1
q)raze((not x)#'"in"),"correct"
"correct"
Or.
q)x:0
q)$[x;"true";"false"]
"false"
q)x:1
q)$[x;"true";"false"]
"true"
Remove leading zeros¶
q)x:"00002345600345000"
q)((x="0")?0b) _ x
"2345600345000"
Remove punctuation characters¶
q)x:"oh! no, stop it. you will?"
q)PUN:",;:.!?"
q)x except y
"oh no stop it you will"
Search¶
Ordinal of word in x pointed at by y¶
q)ow:{sum not y<1+where x=" "}
q)x:"ordinal of word in x pointed at by y"
q)ow[x;5]
0
q)ow[x;6]
0
q)ow[x;7]
0
q)ow[x;8]
1
q)ow[x;26]
5
Find start of string x in string y¶
q)x:"st"
q)y:"indexes of start of string x in string y"
q)y ss x
11 20 32
Find first occurrence of string x in string y¶
q)x:"st"
q)y:"index of first occurrence of string x in string y"
q)first y ss x
12
Locate quotes and text between them¶
q)x:"The \"quick\" brown fox jumps over the \"lazy\" dog."
q)(<>)scan x="\""
000011111100000000000000000000000000011111000000b
q)(or)prior(<>)scan x="\""
000011111110000000000000000000000000011111100000b
q)x where (or)prior (<>)scan x="\""
"\"quick\"\"lazy\""
Or, for a single pair of quotes.
q)x:"abc\"de\"f"
q)count x
8
q)a:x="\""
q)a
00010010b
q)b:where a
q)b
3 6
q)c:(first b)+til 1+ neg -/[b]
q)c
3 4 5 6
q)@[(count x)#0;c;:;1]
0 0 0 1 1 1 1 0
Locate text between quotes¶
q)x
"The \"quick\" brown fox jumps over the \"lazy\" dog."
q)x="\""
000010000010000000000000000000000000010000100000b
q)(<>)prior x="\""
000011000011000000000000000000000000011000110000b
q)(<>)scan x="\""
000011111100000000000000000000000000011111000000b
q)(and)prior(<>)scan x="\""
000001111100000000000000000000000000001111000000b
q)x where(and)prior(<>)scan x="\""
"quicklazy"
Or, for a single pair of quotes.
q)x:"abc\"de\"f"
q)show b:where x="\""
3 6
q)show c:b+1 -1
4 5
q)d:(first c)+til 1+neg(-)over c
q)d
4 5
q)@[(count x)#0;d;:;1]
0 0 0 0 1 1 0 0
Depth of parentheses¶
q)x:"a(b((c)de)f)g(h)"
q)"()"=\:x
0101100000000100b
0000001001010001b
q)({x-0b,-1_y}/)"()"=\:x
0 1 0 1 1 0 0 -1 0 0 -1 0 -1 1 0 0i
q)sums({x-0b,-1_y}/)"()"=\:x
0 1 1 2 3 3 3 2 2 2 1 1 0 1 1 1i
First word in string x¶
q)x:"twas brillig and the slith"
q)x?" "
4
q)(x?" ")#x
"twas"
q)fw:{(x?" ")#x}
q)fw x
"twas"
Substrings¶
Insert blank in y after flag in x¶
q)x:1 0 0 0 0 1 0 0
q)y:"abcdefgh"
q)y,'x#'" "
"a "
,"b"
,"c"
,"d"
,"e"
"f "
,"g"
,"h"
q)raze y,'x#'" "
"a bcdef gh"
Or.
q)c:count[x]+sum x
q)@[c#" ";til[c]except where x;:;y]
" abcd efgh"
Insert x[i] blanks after y[g[i]]¶
q)y:"Thequickbrownfox."
q)g:2 7 12 16
q)x:2 3 4 5
q)(0,1+ -1 _ g_ _ y
'(
[0] (0,1+ -1 _ g_ _ y
^
q)(0,1+ -1 _ g) _ y
"The"
"quick"
"brown"
"fox."
q)raze((0,1+g)_y),'(x,0)#'" "
"The quick brown fox. "
See also 265.
Spread flagged field heads right¶
q)x:"abcdef"
q)y:1 1 0 0 1 0
q)a:where y
q)a
0 1 4
q)a _ x
,"a"
"bcd"
"ef"
q)count a _ x
3
q)count each a _ x
1 3 2
q)
q)b:count each a _ x
q)c:b#'a
q)c
,0
1 1 1
4 4
q)d:raze c
q)d
0 1 1 1 4 4
q)x[d]
"abbbee"
q)x raze(count each a _ x)#'a:where y
"abbbee"