成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

6. Q語言學(xué)習(xí)之路—函數(shù)

Jensen / 2152人閱讀

摘要:接下來幾章將進(jìn)入語言的核心內(nèi)容函數(shù)表數(shù)據(jù)轉(zhuǎn)換查詢和等等,函數(shù)說明在中,函數(shù)是可以修改全局變量的,所以并不是一個(gè)純正的函數(shù)式語言。函數(shù)體內(nèi)最大的局部變量個(gè)數(shù)為個(gè)。當(dāng)執(zhí)行操作時(shí),當(dāng)前項(xiàng)是函數(shù)的左運(yùn)算元,前一項(xiàng)是函數(shù)的右運(yùn)算元。

接下來幾章將進(jìn)入Q語言的核心內(nèi)容——函數(shù)、表、數(shù)據(jù)轉(zhuǎn)換、查詢和I/O等等, excited :)

1. 函數(shù)說明

在q中,函數(shù)是可以修改全局變量的,所以q并不是一個(gè)純正的函數(shù)式語言。
1. 函數(shù)定義
使用花括號(hào){},函數(shù)的輸入輸出類型不用指定,甚至函數(shù)名都可以不用指定。如下是一個(gè)完整的函數(shù)定義:

q) {[x] x*x}

調(diào)用函數(shù)時(shí),參數(shù)用中括號(hào)包圍起來,參數(shù)通過分號(hào);分隔

q){[x] x*x}[3]
9

函數(shù)可以賦值給一個(gè)變量:

q)f:{[x] x*x}
q)f[3]
9

2. 函數(shù)標(biāo)識(shí)和術(shù)語
函數(shù)的正式定義為{[p1;...;pn] e1; ...; em},其中可選的p1;...;pn是正式的參數(shù),e1; ...; em是執(zhí)行的表達(dá)式,雖然是從左向右寫的,但是仍然是從右向左執(zhí)行的。

函數(shù)的參數(shù)個(gè)數(shù)被稱為函數(shù)的valence, 最常見的函數(shù)是monadic(valence 1)dyadic(valence 2)

一個(gè)niladic函數(shù)是指一個(gè)沒有輸入的函數(shù),表示如下:

f:{[] … }

例子如下:

q){[] 42} / pure function returns constant 42
42
q){[] a*a} / impure function: references global a
{[] a*a}

函數(shù)最大的參數(shù)個(gè)數(shù)(valence)為8,超過8個(gè)參數(shù)將會(huì)報(bào)錯(cuò)。如果參數(shù)較多的話,將參數(shù)打包成list或者dictionary輸入函數(shù)。

函數(shù)的輸出值為函數(shù)最后一個(gè)表達(dá)式的結(jié)果:

q){[x] x*x}
q){[x;y] a:x*x; b:y*y; r:a+b; r}
Keep it short. 很多q語言中的函數(shù)都是緊湊并且模塊化的,很多函數(shù)都是僅僅一行

3. 函數(shù)應(yīng)用
函數(shù)的調(diào)用是嚴(yán)格的,意味著在參數(shù)替換之前,表達(dá)式就已經(jīng)被執(zhí)行了:

q)f:{[x] x*x}
q)f[0N!3+1]
4
16

當(dāng)提供的參數(shù)多于函數(shù)定義的參數(shù)時(shí),會(huì)報(bào)"rank錯(cuò)誤。

q) {[x] x*x}[3;4]
"rank

4. 沒有返回值的函數(shù)
函數(shù)體最后只有一個(gè)分號(hào);,返回::

q)fvoid:{[x] `a set x;}
q)fvoid 42
q)a
42

注意在q中,分號(hào);分隔符而并不是終止符

5. 參數(shù)的并列寫法
類似于列表索引和字典取值,函數(shù)的參數(shù)也可以是并列寫法:

q){[x] 2*x} 42
84
q)f:{[x] x*x}
q)f 5
25

6. 函數(shù)名的應(yīng)用
當(dāng)函數(shù)被賦值給一個(gè)全局變量時(shí),可以通過symbol形式的函數(shù)名來調(diào)用:

q)f:{x*x}
q)f[5]
25
q)`f[5]
25
q)`f 5
25
q).my.name.space.f:{2*x}
q)`.my.name.space.f[5]
10

7. 隱含的參數(shù)
當(dāng)一個(gè)函數(shù)沒有參數(shù)被明確定義時(shí),三個(gè)隱含的參數(shù)x, y, z會(huì)被自動(dòng)定義,下面的函數(shù)定義是等價(jià)的:

{[x] x*x}
{x*x}
{[x;y] x+y}
{x+y}

三個(gè)參數(shù)x, y, z的調(diào)用是按照先后順序的,意味著x總是第一個(gè)被調(diào)用,y第二個(gè),z第三個(gè)。下面這個(gè)函數(shù)只有提供三個(gè)參數(shù)值時(shí)才會(huì)返回值

q)g:{x+z}  / likely meant x+y; requires 3 args in call
q)g[1;2]   / still waiting for 3rd arg – i.e., a projection
{x+z}[1;2]
q)g[1;2;3] / 2nd arg is required but ignored
4

8. 匿名函數(shù)和lambda表達(dá)式
一個(gè)沒有函數(shù)名稱的函數(shù)叫做匿名函數(shù),匿名函數(shù)的常見的兩個(gè)用處:

定義在函數(shù)內(nèi)的匿名函數(shù)

f{[...] ...; {...}[...]; ...}

函數(shù)容器

q)powers:({1}; {x}; {x*x}; {x*x*x})
…
q)selected:2
q)powers[selected]
{x*x}

9. 恒等函數(shù)::
恒等函數(shù)::返回它的輸入作為輸出;裸的恒等函數(shù)不能使用并列的形式,它必須使用中括號(hào)調(diào)用。

q)::[42]
42
q)::[`a`b`c]
`a`b`c
q):: 42 / error
"
q)(::) 42
42

10. 函數(shù)是數(shù)據(jù)
類似于python中的函數(shù)是對(duì)象一樣,在q語言中函數(shù)都是數(shù)據(jù),可以作為輸入和輸出。

q)apply:{x y}
q)sq:{x*x}
q)apply[sq; 5]
25
2. 通過名字調(diào)用

常規(guī)的函數(shù)使用傳值調(diào)用(call-by-value),意味著參數(shù)在被傳遞時(shí)是按值傳遞的,在這個(gè)過程中,原始值被拷貝了一份,以保證之前的原始數(shù)據(jù)不會(huì)被修改。但這樣做的一個(gè)問題是,當(dāng)輸入?yún)?shù)的size非常大時(shí),拷貝是被禁止的。這個(gè)時(shí)候就有一個(gè)新的方法:call-by-name,在這種情況下變量的名字被傳遞而不是變量的值。

Call-by-name沒有特別的語法。一個(gè)例子就是內(nèi)置函數(shù)get,傳遞全局變量的名字,返回對(duì)應(yīng)的值

q)a:42
q)get `a
42

另一個(gè)例子是函數(shù)set,是給全局變量賦值

q)`a set 43
`a
q)a
43
3. 局部和全局變量

1. 定義局部和全局變量
在函數(shù)體內(nèi)使用:定義的變量被稱為局部變量。函數(shù)體內(nèi)最大的局部變量個(gè)數(shù)為24個(gè)。

q)f:{a:42; a+x}

q語言不遵循詞法作用域規(guī)則,意味著在函數(shù)體內(nèi)的函數(shù)并沒有獲得上層函數(shù)體內(nèi)變量的權(quán)限,例如下例中, helper函數(shù)并沒有獲取局部變量a的值的權(quán)限

q)f:{[p1] a:42; helper:{[p2] a*p2}; helper p1}

然而,你必須對(duì)該局部函數(shù)聲明一個(gè)額外的參數(shù)來傳遞局部變量

q)f:{[p1] a:42; helper:{[a; p2] a*p2}[a;]; helper p1}
q)f 5
210

在所有函數(shù)定義以外的變量被稱為全局變量。

2. 在函數(shù)內(nèi)對(duì)全局變量賦值
當(dāng)函數(shù)體內(nèi)沒有同名的局部變量時(shí),可以使用雙冒號(hào)::來對(duì)全局變量進(jìn)行賦值;
`q)b:6
q)f:{b::7; x*b}
q)f[6]
42
q)b
7`
而當(dāng)函數(shù)體內(nèi)有同名的局部變量時(shí),雙冒號(hào)符操作的是局部變量,并不是全局變量

q)b:6
q)f:{b:42; b::x; b}
q)f[98]
98
q)b
6

相比::,更推薦使用set來進(jìn)行全局變量修改, 這樣就不會(huì)有局部變量名沖突了。

q)a:42
q)f:{a:98.6; `a set x}
q)f 43
`a
q)a
43
4. 投影

投影是指只指定函數(shù)的一部分參數(shù),其結(jié)果會(huì)是其余參數(shù)的函數(shù)。

1. 函數(shù)投影
一個(gè)函數(shù)投影的例子為:

q)add:{x+y}
q)add[42;]
{x+y}[42;]

q)add[42;][3]
45
q)add3:{x+y+z}
q)add3[2][3][4]
9

上式可以理解為add3作用于參數(shù)2,返回一個(gè)函數(shù);該函數(shù)作用于參數(shù)3,返回一個(gè)函數(shù);最后作用于4,返回結(jié)果9。上式等價(jià)于add3[2;3;4]。

No second look. 被賦值的函數(shù)投影變量不會(huì)隨著原函數(shù)的改變而改變
q)f:{x-y}
q)g:f[42;]
q)g
{x-y}[42;]
q)g[6]
36
q)f:{x+y}
q)g
{x-y}[42;]
q)g[6]
36

2. 運(yùn)算符投影
當(dāng)使用運(yùn)算符中綴形式的時(shí)候,一個(gè)q的運(yùn)算符可以通過固定其左運(yùn)算元來進(jìn)行投影,這時(shí)需要括號(hào)。

q)(7*) 6
42

由于任何操作符都是一個(gè)函數(shù),當(dāng)然可以使用其前綴形式進(jìn)行投影:

q)-[;42] 98
56

上面兩個(gè)公式中的空格符都不是必須的:

q)(7*)6
42
q)-[;42]98
56

3. 多維投影
當(dāng)函數(shù)有多個(gè)參數(shù)的時(shí)候(valence > 2),函數(shù)可以有多個(gè)投影,例如下例

q){x+y+z}[1;;3]
{x+y+z}[1;;3]
q){x+y+z}[1;;3] 2
6
5. Atomic函數(shù)

一個(gè)Atomic函數(shù)是指該函數(shù)直接作用于一個(gè)q數(shù)據(jù)結(jié)構(gòu)中的atom數(shù)據(jù)。

1. Monadic Atomic函數(shù)和map
回憶一下,monadic函數(shù)是指只作用于一個(gè)參數(shù)的函數(shù),如下是一個(gè)monadic atomic函數(shù)的例子,該函數(shù)作用于一個(gè)字典

q)neg 10
-10
q)neg 10 20 30
-10 -20 -30
q)neg (10 20 30; 40 50)
-10 -20 -30
-40 -50
q)neg `a`b`c!10 20 30
a| -10
b| -20
c| -30
q)neg `a`b`c!(10 20; 30 40 50; 60)
a| -10 -20
b| -30 -40 -50
c| -60

2. Dyadic atomic函數(shù)和zip
Dyadic函數(shù)是指作用于兩個(gè)參數(shù)的函數(shù)。若將dyadic函數(shù)的非atomic部分固定下來(可以看成一個(gè)函數(shù)的投影),那么dyadic函數(shù)就變?yōu)閙onadic函數(shù)。如下例中的dyadic操作符?。

q)10 20 30?10
0
q)10 20 30?10 20 30 40 50
0 1 2 3 3
q)(enlist 10)?10
0
q)10 20?10
0
q)10 20 30 40 50?10
0

在算術(shù)中,比較和關(guān)系運(yùn)算符都是atomic的,在這種應(yīng)用下會(huì)有四種情況:

atom和atom

atom和list

list和atom

list和list

在最后一種情況下,兩個(gè)list元素的長度必須相等

q)1+10
11
q)1+10 20 30
11 21 31
q)1 2 3+10
11 12 13
q)1 2 3+10 20 30
11 22 33

這個(gè)功能相當(dāng)于傳統(tǒng)語言中的zip

3. 構(gòu)造atomic函數(shù)
簡單想一想就可以明白,由atomic函數(shù)構(gòu)成的函數(shù)仍然是atomic的,因此構(gòu)造一個(gè)atomic函數(shù)的方法就是去包含內(nèi)置的atomic函數(shù)。

構(gòu)造Monadic atomic函數(shù):

q)f:{(x*x)+(2*x)-1}
q)f 0
-1
q)f til 10
-1 2 7 14 23 34 47 62 79 98

構(gòu)造Dyadic atomic函數(shù):

q)pyth:{sqrt (x*x)+y*y}
q)pyth[1; 1]
1.414214
q)pyth[1; 1 2 3]
1.414214 2.236068 3.162278
q)pyth[1 2 3; 1 2 3]
1.414214 2.828427 4.242641
6. 副詞

副詞是高階的函數(shù),用以改變函數(shù)在列表上的應(yīng)用方式。這個(gè)術(shù)語來自于將q操作符當(dāng)做動(dòng)詞。

Proficiency in the use of adverbs is one skill that separates q pretenders from q contenders. :)

1. Monadic each
合并函數(shù)例如count只會(huì)作用在嵌套列表的最高層級(jí):

q)count 10 20 30
3
q)count (10 20 30; 40 50)
2

如果我們想知道嵌套列表中每個(gè)元素的長度,這個(gè)時(shí)候副詞each就派上用場(chǎng)了,它使得monadic函數(shù)能夠作用于列表的每個(gè)元素而不是整個(gè)列表,each有兩種使用方法:

中綴形式:each緊跟在函數(shù)的后面

q) count each (10 20 30; 40 50)
3 2

前綴形式

q) each[count] (10 20 30; 40 50)
3 2

對(duì)于層數(shù)較深的嵌套矩陣,可能需要對(duì)each進(jìn)行迭代

q)(count each) each ((1 2 3; 3 4); (100 200; 300 400 500))
3 2
2 3
q)each[each[count]] ((1 2 3; 3 4); (100 200; 300 400 500))
3 2
2 3

一些例子:

q)reverse "live"
"evil"
q)reverse ("life"; "the"; "universe"; "and"; "everything")
q)reverse each ("life"; "the"; "universe"; "and"; "everything")

當(dāng)想要將一個(gè)長度為n的向量轉(zhuǎn)換為一個(gè)大小為n*1的矩陣時(shí),可以使用enlist each來實(shí)現(xiàn),但flip enlist在大列表上執(zhí)行更快。

q)enlist each 1001 1002 1004 1003
1001
1002
1004
1003
q)flip enlist 1001 1002 1004 1003
1001
1002
1004
1003

2. each-both"
副詞each-both符號(hào)"作用在一個(gè)dyadic函數(shù)上,使得函數(shù)能夠成對(duì)地作用在對(duì)應(yīng)的列表元素上,符號(hào)"讀作"zip"

q)("abc"; "uv"),"("de"; "xyz")
"abcde"
"uvxyz"
q)1,"10 20 30
1 10
1 20
1 30
q)1 2 3,"10
1 10
2 10
3 10
q)2#"("abcde"; "fgh"; "ijklm")
"ab"
"fg"
"ij"

當(dāng)熟練的時(shí)候,可以使用each-both的前綴形式:

q),"[("abc"; "uv"); ("de"; "xyz")]
"abcde"
"uvxyz"

一個(gè)table的例子:

q)t1:([] c1:1 2 3)
q)t2:([] c2:`a`b`c)
q)t1,"t2
c1 c2
-----
1  a
2  b
3  c

3. each-left :
each-left操作符作用于一個(gè)dyadic函數(shù),使第一個(gè)參數(shù)下的每一項(xiàng)都應(yīng)用于第二個(gè)參數(shù):

("abc"; "de"; enlist "f") ,: ">"
"abc>"
"de>"
"f>"

4. each-right /:
each-right 作用于一個(gè)dyadic函數(shù),使第一項(xiàng)作用于第二個(gè)參數(shù)的每一項(xiàng):

q)"

5. Cross Product
叉積(Cross Product)成對(duì)地作用于左側(cè)的每一項(xiàng)和右側(cè)的每一項(xiàng)。 如果我們對(duì)join執(zhí)行each-righteach-left操作,再內(nèi)置函數(shù)raze對(duì)得到的嵌套矩陣夷平,就可以得到我們想要的結(jié)果

q)1 2 3,/::10 20
1 10 1 20
2 10 2 20
3 10 3 20
q)raze 1 2 3,/::10 20
1 10
1 20
2 10
2 20
3 10
3 20

上述操作還是較為復(fù)雜,我們可以通過內(nèi)置函數(shù)cross來得到上述結(jié)果

q)1 2 3 cross 10 20
1 10
1 20
2 10
2 20
3 10
3 20

可以注意到,若我們組合each-lefteach-right時(shí),我們便可以得到上述結(jié)果的轉(zhuǎn)置

q)raze 1 2 3,:/:10 20
1 10
2 10
3 10
1 20
2 20
3 20

6. Over /
Over操作符/是一個(gè)提供遞歸機(jī)制的高階函數(shù)。它最簡單的形式是修改一個(gè)dyadic函數(shù),使其在一個(gè)list上累積函數(shù)作用的結(jié)果

q)0 +/ 1 2 3 4 5 6 7 8 9 10
55

注意: 在運(yùn)算符和/之間不能存在空格,因?yàn)?b>/可以被用作注釋。

運(yùn)算符左運(yùn)算元為累積計(jì)算的初始值,右運(yùn)算元為待累積計(jì)算的列表。

但我們也可以省略左運(yùn)算元(即初始值),這個(gè)時(shí)候需要我們對(duì)表達(dá)式做一些變換,被作用函數(shù)和Over運(yùn)算符/括號(hào)包住,這時(shí)右邊列表的第一個(gè)元素就是初始值。

q)(+/) 1 2 3 4 5 6 7 8 9 10
55

上面的括號(hào)是必需項(xiàng),被修改的函數(shù)實(shí)際上是一個(gè)monadic函數(shù)。

一些有用的over形式:

q)(*/) 1 2 3 4 5 6 7 8 9 10 / product
3628800
q)(|/) 7 8 4 3 10 2 1 9 5 6 / maximum
10
q)(&/) 7 8 4 3 10 2 1 9 5 6 / minimum
1

使用,/可以高效地移除列表的頂層嵌套,其對(duì)應(yīng)的內(nèi)置函數(shù)為raze

q)(,/)((1 2 3; 4 5); (100 200; 300 400 500))
1 2 3
4 5
100 200
300 400 500
q)raze ((1 2 3; 4 5); (100 200; 300 400 500))
1 2 3
4 5
100 200
300 400 500

7. Iteration
/的另一種用法是作為循環(huán)代碼的等價(jià)形式。在這個(gè)版本下,左運(yùn)算元表示了循環(huán)的次數(shù),右運(yùn)算元為初始值。例如,計(jì)算Fibonacci數(shù)列:

q)fib:{x, sum -2#x}
q)10 fib/ 1 1
1 1 2 3 5 8 13 21 34 55 89 144
q)fib/[10;1 1]
1 1 2 3 5 8 13 21 34 55 89 144

另一個(gè)版本的/控制了循環(huán)的進(jìn)行直至收斂,或者檢測(cè)到一個(gè)環(huán)的存在。下面以牛頓法為例介紹這種循環(huán)的使用,我們使用牛頓法來尋找函數(shù){-2+x*x}的根:

q)f:{-2+x*x}
q)secant:{[f;x;e] (f[x+e]-f x-e)%2*e}
q){x-f[x]%secant[f; x; 1e-6]}/[1.5]
1.414214

q語言會(huì)判斷當(dāng)前的輸出值與之前的輸出值之間的大小,如果兩個(gè)值之間相差在一定的tolerance以內(nèi),則認(rèn)為算法收斂并且迭代完成;否則繼續(xù)執(zhí)行循環(huán)任務(wù)。

此外,q語言通過每次比較運(yùn)算結(jié)果和初始值是否match(~)來判斷當(dāng)前程序是否存在環(huán)(loop),如果存在環(huán),程序則終止:

q)newtcycle:{[xn] xn-((xn*xn*xn)+(-2*xn)+2)%-2+3*xn*xn}
q)newtcycle/[0.0]
1f

如果運(yùn)算的結(jié)果與初始值相等,但是類型不同(not match),程序則不會(huì)停止;例如上例中如果提供初始值0,則程序會(huì)一直運(yùn)行下去。

運(yùn)算符/的最后一種重載用法,等價(jià)于使用while循環(huán),它提供了一個(gè)判斷條件,若每次的運(yùn)算結(jié)果滿足條件,則繼續(xù)執(zhí)行;否則,終止計(jì)算

q)fib:{x,sum -2#x}
q)fib/[{1000>last x}; 1 1]
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

8. Scan
Scan操作符同樣是一個(gè)高階函數(shù),其作用與操作符/一樣,與其不同的是,Scan會(huì)返回中間的計(jì)算結(jié)果??梢园裇can當(dāng)做是Over/的"running"版本。

q)0+1 2 3 4 5 6 7 8 9 10
1 3 6 10 15 21 28 36 45 55

q)(*)1 2 3 4 5 6 7 8 9 10

q)(|)7 8 4 3 10 2 1 9 5 6
7 8 8 8 10 10 10 10 10 10

q)(&)7 8 4 3 10 2 1 9 5 6
7 7 4 3 3 2 1 1 1 1

q)100 f1 2 3 4 5 6 7 8 9 10

q)(f)1 2 3 4 5 6 7 8 9 10

所有over操作符/的用法都適用于Scan操作符,使用Scan操作符的好處是可以看到函數(shù)中間過程的運(yùn)行結(jié)果。

q)fib:{x, sum -2#x}
q)fib[{1000>last x}; 1 1]

9. each-previous ":
each-previous操作符對(duì)列表的每項(xiàng)和其前一項(xiàng)執(zhí)行dyadic函數(shù)操作。當(dāng)執(zhí)行Dyadic操作時(shí),當(dāng)前項(xiàng)是Dyadic函數(shù)的左運(yùn)算元,前一項(xiàng)是Dyadic函數(shù)的右運(yùn)算元。

由于列表中第一項(xiàng)沒有前項(xiàng),所以我們必須在運(yùn)算符:"左運(yùn)算元的位置提供初始值,如下例

q)100 -": 100 99 101 102 101
0 -1 2 1 -1

與其它副詞一樣,each-previous :"也有一個(gè)monadic函數(shù)的形式。但在這種形式下,列表中的第一個(gè)元素不會(huì)被當(dāng)做初始的前項(xiàng),相反,它直接返回該項(xiàng)。

q)(-":)100 99 101 102 101
100 -1 2 1 -1
q)deltas 100 99 101 102 101
100 -1 2 1 -1
q)(%":)100 99 101 102 101
100 0.98999999999999999 1.0202020202020201 1.0099009900990099 0.99019607843137258
q)ratios 100 99 101 102 101
100 0.98999999999999999 1.0202020202020201 1.0099009900990099 0.99019607843137258

保留第一項(xiàng)的動(dòng)機(jī)是,可以通過保留的第一項(xiàng)來恢復(fù)整個(gè)list

q)sums deltas 100 99 101 102 101
100 99 101 102 101
q)deltas sums 100 99 101 102 101
100 99 101 102 101

當(dāng)我們需要返回的結(jié)果中都是變化值時(shí),可以通過如下方法得到

q)deltas0:{first[x] -": x}
q)deltas0 100 99 101 102 101
0 -1 2 1 -1

一個(gè)使用each-previous的非常有用的工具是使用~判斷連續(xù)項(xiàng)是否是match的。實(shí)際中,我們經(jīng)常會(huì)關(guān)注兩個(gè)連續(xù)項(xiàng)不同的情況,這種情況下使用內(nèi)置函數(shù)differ

q)(~":) 1 1 1 2 2 3 4 5 5 5 6 6
011010001101b
q)not (~":) 1 1 1 2 2 3 4 5 5 5 6 6
100101110010b
q)differ 1 1 1 2 2 3 4 5 5 5 6 6
100101110010b

可以對(duì)differ的結(jié)果使用wherecut來分隔列表

q)L:1 1 1 2 2 3 4 5 5 5 6 6
q)where differ L
0 3 5 6 7 10
q)(where differ L) cut L
1 1 1
2 2
,3
,4
5 5 5
6 6

下面我們來做一些q的練習(xí)

q)runs:(where differ L) cut L / store runs
q)ct:count each runs / store count of each run
q)runs where ct=max ct / find the runs of maximum length
1 1 1
5 5 5

用一行代碼來實(shí)現(xiàn)上面的代碼

q) runs where ct=max ct:count each runs:(where differ L) cut L

同樣,我們可以上述技術(shù)來找到上升和下降子序列

q)L:9 8 7 11 10 12 13
q)(where -0W>":L) cut L
9 8 7
11 10
,12
,13
q)(where 0W<":L) cut L
,9
,8
7 11
10 12 13
8. 一般應(yīng)用
Thorough understanding of the general application is another test that separates the q pretenders from the contenders.

1. 動(dòng)詞 @
q語言的基礎(chǔ)操作包括:從list中通過索引取值,在字典中通過鍵取值或執(zhí)行一個(gè)monadic函數(shù)。
高階函數(shù)@是q語言中基礎(chǔ)操作的真正形式,它將一個(gè)monadic映射(可能是索引取值,字典取值或者monadic函數(shù))作用于一個(gè)元素之上。與所有的內(nèi)置函數(shù)一樣,它同樣有中綴和前綴的表示形式

q)10 20 30 40@1
20
q)L:10 20 30 40
q)L@1
20
q)@[L; 1]
20
q)count@L
4
q)@[count; L]
4
q){x*x}@L
100 300 900 1600
q)d:`a`b`c!10 20 30
q)d@`a
10
q)@[d;`b]
20

當(dāng)@niladic函數(shù)應(yīng)用時(shí),可以使用空元素::來代表空值

q)f:{6*7}
q)f[]
42
q)@[f; ::]
42
q)f@(::)
42
q)f@43
42

2. 動(dòng)詞.
q語言中,多元映射包括了:深度索引一個(gè)列表,從一個(gè)字典中取一個(gè)被嵌套的值和執(zhí)行一個(gè)帶有多個(gè)參數(shù)的函數(shù)等。高階函數(shù).是q語言中多元應(yīng)用的真正形式。它將多元映射投影到多個(gè)參數(shù)上,并且可以被寫為中綴和前綴形式。

.的右側(cè)必須是一個(gè)list

q)L:(10 20 30; 40 50)
q)L[1][0]
40
q)L[1; 0]
40
q)L . 1 0
40
q)d:`a`b`c!(10 20 30; 40 50; enlist 60)
q)d[`b][0]
40
q)d[`b; 0]
40
q)d . (`b; 0)
40
q)g:{x+y}
q)g[1; 2]
3
q)g . 1 2
3

可以配合monadic函數(shù)使用.,其效果如下

q)f:{x*x}
q)f@5
25
q)f . enlist 5
25
q)f . enlist 1 2 3
1 4 9

為了表示一個(gè)隱藏的索引,可以使用::來代替

q)m:(1 2 3;4 5 6)
q)m[0;]
1 2 3
q)m . (0; ::)
1 2 3
q)m . (::; 1)
2 5

對(duì)于一個(gè)niladic函數(shù)的.執(zhí)行形式,需要使用::生成一個(gè)list。

q)f:{6*7}
q)f . enlist (::)
42
q)f . enlist 42
42
All data structures in q are composed from lists and dictionaries.

一些很好的練習(xí):

q)L:10 20 30
q)L . enlist 1
_
q)m:(10 20 30; 100 200 300)
q)m . 0 1
_
q)ds:(`a`b`c!10 20 30; `x`y!100 200)
q)ds . (0; `b)
_
q)mix:(10 20 30; `a`b`c!(1; 2; (300 400)))
q)mix . (1; `c; 1)
_
q)dc:`c1`c2!(1 2 3; `a`b`c)
q)dc . (`c2; 1)
_
q)t:([]c1:1 2 3;c2:`a`b`c)
q)t . (1; `c2)
_

答案分別是
20
20
20
400
`b
`b

3. 應(yīng)用Monadic函數(shù)的@

回憶@的一般操作:

q)L:10 20 30 40 50
q)@[L;1]
20
q)@[L;0 1]
10 20

現(xiàn)在除了取值外,我們同時(shí)應(yīng)用一個(gè)函數(shù):

q)@[L;1;neg]
10 -20 30 40 50
q)@[L;0 2;neg]
-10 20 -30 40 50

注意到上述結(jié)果與正常在列表子集上的運(yùn)算不同,正常只會(huì)返回在子集上運(yùn)算的結(jié)果

q)neg L@0 1
-10 -20

而這個(gè)提升的版本會(huì)返回修改后的整個(gè)列表

Monadic函數(shù)使用@的一般應(yīng)用 的語法是

@[L;I;f]

其中L是列表,I為索引的容器。這個(gè)形式可以泛化到任何可以被視為映射的數(shù)據(jù)結(jié)構(gòu),例如給定一個(gè)字典和一個(gè)鍵值列表

q)d:`a`b`c!10 20 30
q)ks:`a`c
q)@[d; ks; neg]
a| -10
b| 20
c| -30

上述操作都是在輸入數(shù)據(jù)結(jié)構(gòu)的拷貝上完成的。我們也可以通過pass-by-name的方法來進(jìn)行in-place修改

q)L:10 20 30 40
q)@[L; 0; neg]
-10 20 30 40
q)L
10 20 30 40
q)@[`L; 0 ; neg]
`L
q)L
-10 20 30 40

4. 應(yīng)用Dyadic函數(shù)的@
當(dāng)Dyadic函數(shù)使用@時(shí),需要提供一個(gè)額外的運(yùn)算元,顯然運(yùn)算元要與子集的大小匹配。除了一種額外的情況,當(dāng)運(yùn)算元是atom時(shí),會(huì)被自動(dòng)拓展到與子集相同大小。

q)L:10 20 30 40
q)@[L; 0 1; +; 100 200]
110 220 30 40
q)@[L; 0 1; +; 100]
110 120 30 40
q)d:`a`b`c!10 20 30
q)@[d; `a`b; +; 100 200]
a| 110
b| 220
c| 30
q)@[d; `a`b; +; 100]
a| 110
b| 120
c| 30

Dyadic函數(shù)使用@的一般應(yīng)用 的語法是

@[L;I;g;v]

其中LI與上小節(jié)定義一樣,可以是任意能夠被視為映射的數(shù)據(jù)結(jié)構(gòu);g是一個(gè)Dyadic函數(shù);v是一個(gè)atom或者與I匹配的列表。

列表賦值: 一個(gè)非常有用的Dyadic函數(shù)應(yīng)用是使用賦值符:在子集上賦值

q)L:10 20 30 40
q)@[L; 0 2; :; 42 43]
42 20 43 40

與Monadic函數(shù)一樣,in-place操作可以通過pass-by-name形式

q)L:10 20 30 40
q)@[`L; 0 2; :; 42 43]
`L
q)L
42 20 43 40

5. 應(yīng)用Monadic函數(shù)的.
總結(jié)一下,@是作用在數(shù)據(jù)結(jié)構(gòu)的頂層,而.則是深度索引。

重新回顧一下.的前綴用法

q)m:(10 20 30; 100 200 300)
q).[m; 0 1]
20
q)d:`a`b`c!(10 20 30; 40 50; enlist 60)
q).[d; (`a; 1)]
20

應(yīng)用monadic函數(shù)的.形式:

q).[m; 0 1; neg]
10 -20 30
100 200 300
q).[d; (`a; 1); neg]
a| 10 -20 30
b| 40 50
c| ,60

同樣,若想in-place修改,則使用pass-by-name形式。

可以使用::來代替隱藏的索引

q).[m; (0; ::); neg]
-10 -20 -30
100 200 300
q)d:`a`b`c!(100 200 300; 400 500; enlist 600)
q).[d; (`a; ::); neg]
a| -100 -200 -300
b| 400 500
c| ,600
q).[d; (::; 0); neg]
a| -100 200 300
b| -400 500
c| ,-600

應(yīng)用monadic函數(shù)的.一般形式為:

.[L; I; f]

7. 應(yīng)用Dyadic函數(shù)的.

一般形式為

.[L;I;g;v]

其中g是Dyadic函數(shù),v是atom或與I相對(duì)應(yīng)的運(yùn)算元

q)m:(10 20 30; 100 200 300)
q).[m; 0 1; +; 1]
10 21 30
100 200 300
q).[m; (::; 1); +; 1 2]
10 21 30
100 202 300
q)m
10 20 30
100 200 300
q).[`m; (::; 1); +; 1]
`m
q)m
10 21 30
100 200 300
q).[`m; (::; 1); :; 42]
`m
q)m
10 42 30
100 42 300
q)d:`a`b`c!(100 200 300; 400 500; enlist 600)
q).[d; (`a; 1); +; 1]
q).[d; (`a; ::); +; 1]
q).[d; (::; 0); +; 1]
q).[`d; (::; 0); :; 42]

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/17969.html

相關(guān)文章

  • 3. Q語言學(xué)習(xí)之路—Lists

    摘要:簡單所有中的元素都是同種類型的,這種列表具有很好的儲(chǔ)存和性能占據(jù)連續(xù)的儲(chǔ)存空間。索引域如果索引在合理的邊界之外,結(jié)果不是一個(gè)錯(cuò)誤,而會(huì)返回一個(gè)值,表示,返回的值類型與第一個(gè)元素的類型一致。其結(jié)果是右側(cè)元素占據(jù)左側(cè)元素,除非右側(cè)元素為值。 0. 概述 所有Q中的數(shù)據(jù)類型最終都是由list構(gòu)造的:一個(gè)字段(dictionary)是由一對(duì)list構(gòu)造的;一個(gè)表是一個(gè)特殊的字典;一個(gè)鍵表(ke...

    wwq0327 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<