亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

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

Jensen / 2288人閱讀

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

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

1. 函數(shù)說明

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

q) {[x] x*x}

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

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

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

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

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

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

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

f:{[] … }

例子如下:

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

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

函數(shù)的輸出值為函數(shù)最后一個表達式的結(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ù)替換之前,表達式就已經(jīng)被執(zhí)行了:

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

當(dāng)提供的參數(shù)多于函數(shù)定義的參數(shù)時,會報"rank錯誤。

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

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

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

注意在q中,分號;分隔符而并不是終止符。

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ù)被賦值給一個全局變量時,可以通過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)一個函數(shù)沒有參數(shù)被明確定義時,三個隱含的參數(shù)x, y, z會被自動定義,下面的函數(shù)定義是等價的:

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

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

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表達式
一個沒有函數(shù)名稱的函數(shù)叫做匿名函數(shù),匿名函數(shù)的常見的兩個用處:

定義在函數(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ù)不能使用并列的形式,它必須使用中括號調(diào)用。

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

10. 函數(shù)是數(shù)據(jù)
類似于python中的函數(shù)是對象一樣,在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ù)據(jù)不會被修改。但這樣做的一個問題是,當(dāng)輸入?yún)?shù)的size非常大時,拷貝是被禁止的。這個時候就有一個新的方法:call-by-name,在這種情況下變量的名字被傳遞而不是變量的值。

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

q)a:42
q)get `a
42

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

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

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

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}

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

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

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

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

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

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

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

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

1. 函數(shù)投影
一個函數(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,返回一個函數(shù);該函數(shù)作用于參數(shù)3,返回一個函數(shù);最后作用于4,返回結(jié)果9。上式等價于add3[2;3;4]。

No second look. 被賦值的函數(shù)投影變量不會隨著原函數(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. 運算符投影
當(dāng)使用運算符中綴形式的時候,一個q的運算符可以通過固定其左運算元來進行投影,這時需要括號。

q)(7*) 6
42

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

q)-[;42] 98
56

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

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

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

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

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

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

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ù)是指作用于兩個參數(shù)的函數(shù)。若將dyadic函數(shù)的非atomic部分固定下來(可以看成一個函數(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)系運算符都是atomic的,在這種應(yīng)用下會有四種情況:

atom和atom

atom和list

list和atom

list和list

在最后一種情況下,兩個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

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

3. 構(gòu)造atomic函數(shù)
簡單想一想就可以明白,由atomic函數(shù)構(gòu)成的函數(shù)仍然是atomic的,因此構(gòu)造一個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)用方式。這個術(shù)語來自于將q操作符當(dāng)做動詞。

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

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

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

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

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

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

前綴形式

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

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

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)想要將一個長度為n的向量轉(zhuǎn)換為一個大小為n*1的矩陣時,可以使用enlist each來實現(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符號"作用在一個dyadic函數(shù)上,使得函數(shù)能夠成對地作用在對應(yīng)的列表元素上,符號"讀作"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)熟練的時候,可以使用each-both的前綴形式:

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

一個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操作符作用于一個dyadic函數(shù),使第一個參數(shù)下的每一項都應(yīng)用于第二個參數(shù):

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

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

q)"

5. Cross Product
叉積(Cross Product)成對地作用于左側(cè)的每一項和右側(cè)的每一項。 如果我們對join執(zhí)行each-righteach-left操作,再內(nèi)置函數(shù)raze對得到的嵌套矩陣夷平,就可以得到我們想要的結(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時,我們便可以得到上述結(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操作符/是一個提供遞歸機制的高階函數(shù)。它最簡單的形式是修改一個dyadic函數(shù),使其在一個list上累積函數(shù)作用的結(jié)果

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

注意: 在運算符和/之間不能存在空格,因為/可以被用作注釋。

運算符左運算元為累積計算的初始值,右運算元為待累積計算的列表。

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

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

上面的括號是必需項,被修改的函數(shù)實際上是一個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

使用,/可以高效地移除列表的頂層嵌套,其對應(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)代碼的等價形式。在這個版本下,左運算元表示了循環(huán)的次數(shù),右運算元為初始值。例如,計算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

另一個版本的/控制了循環(huán)的進行直至收斂,或者檢測到一個環(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語言會判斷當(dāng)前的輸出值與之前的輸出值之間的大小,如果兩個值之間相差在一定的tolerance以內(nèi),則認(rèn)為算法收斂并且迭代完成;否則繼續(xù)執(zhí)行循環(huán)任務(wù)。

此外,q語言通過每次比較運算結(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

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

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

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操作符同樣是一個高階函數(shù),其作用與操作符/一樣,與其不同的是,Scan會返回中間的計算結(jié)果。可以把Scan當(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ù)中間過程的運行結(jié)果。

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

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

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

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

與其它副詞一樣,each-previous :"也有一個monadic函數(shù)的形式。但在這種形式下,列表中的第一個元素不會被當(dā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

保留第一項的動機是,可以通過保留的第一項來恢復(fù)整個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é)果中都是變化值時,可以通過如下方法得到

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

一個使用each-previous的非常有用的工具是使用~判斷連續(xù)項是否是match的。實際中,我們經(jīng)常會關(guān)注兩個連續(xù)項不同的情況,這種情況下使用內(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

可以對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

用一行代碼來實現(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. 動詞 @
q語言的基礎(chǔ)操作包括:從list中通過索引取值,在字典中通過鍵取值或執(zhí)行一個monadic函數(shù)。
高階函數(shù)@是q語言中基礎(chǔ)操作的真正形式,它將一個monadic映射(可能是索引取值,字典取值或者monadic函數(shù))作用于一個元素之上。與所有的內(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)用時,可以使用空元素::來代表空值

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

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

.的右側(cè)必須是一個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

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

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

對于一個niladic函數(shù)的.執(zhí)行形式,需要使用::生成一個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)在除了取值外,我們同時應(yīng)用一個函數(shù):

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

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

q)neg L@0 1
-10 -20

而這個提升的版本會返回修改后的整個列表。

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

@[L;I;f]

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

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的方法來進行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ù)使用@時,需要提供一個額外的運算元,顯然運算元要與子集的大小匹配。除了一種額外的情況,當(dāng)運算元是atom時,會被自動拓展到與子集相同大小。

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是一個Dyadic函數(shù);v是一個atom或者與I匹配的列表。

列表賦值: 一個非常有用的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相對應(yīng)的運算元

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)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/17969.html

相關(guān)文章

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

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

    wwq0327 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<