2017-06-13 56 views
1

如何根據其他向量的值有效且簡潔地切換公式?[KDB +/Q]:有條件的嵌套向量

kx documentation,有可能

已經不僅僅是一個真/假的選擇,例如更MATCH1/MATCH2/MATCH3 /其他映射RESULT1/RESULT2/result3 /默認

數據:

q)t:([]a:til 5;b:10+til 5;c:100+til 5;d:1000+til 5;g:`I`B`I`U`B) 
a b c d g 
--------------- 
0 10 100 1000 I 
1 11 101 1001 B 
2 12 102 1002 I 
3 13 103 1003 U 
4 14 104 1004 B 

我已經做了這樣的:

q)update r:(flip (a+b;c+d;a-d))@'`I`B`U?g from t 
a b c d g r  
--------------------- 
0 10 100 1000 I 10 
1 11 101 1001 B 1102 
2 12 102 1002 I 14 
3 13 103 1003 U -1000 
4 14 104 1004 B 1108 

問題 - 有更有效的方式(時間,空間,代碼行)?

回答

1

這類似於你的解決方案,但似乎約30%的速度,可能是因爲沒有flip

q)update r: ((a+b;c+d;a-d)@(`I`B`U?g))@'i from t 
a b c d g r 
--------------------- 
0 10 100 1000 I 10 
1 11 101 1001 B 1102 
2 12 102 1002 I 14 
3 13 103 1003 U -1000 
4 14 104 1004 B 1108 

q)t:1000000?t 
q)\t update r: ((a+b;c+d;a-d)@(`I`B`U?g))@'i from t 
166 
q)\t update r:(flip (a+b;c+d;a-d))@'`I`B`U?g from t 
248 

儘管嵌套條件仍然看起來更快:

q)\t update r:?[`I=g;a+b;?[`B=g;c+d;a-d]] from t 
46 
+0

'@'我'是輝煌!在我繼續從右至左重複使用「@」系列之前,我有一種新的成語。謝謝! –

1

可以使用條件的載體: http://code.kx.com/q/ref/lists/#vector-conditional

q)update r:?[`I=g;a+b;c+d] from t 
    a b c d g r 
    -------------------- 
    0 10 100 1000 I 10 
    1 11 101 1001 B 1102 
    2 12 102 1002 I 14 
    3 13 103 1003 I 16 
    4 14 104 1004 B 1108 

編輯: 當G有多個值超過兩個,你可以進一步嵌套條件擴展:

q)\t res2:delete idx from`idx xasc raze{[t;idx;it;k] @[d;`idx`r;:;](idxs; 
    (+).(d:t idxs:idx[it])k)}[t;group t`g;]./:flip(`I`C`B;(`a`b;`b`c;`c`d)) 
    122 
    q) 
    q)\t res3:update r:?[`I=g;a+b;?[`B=g;c+d;a-d]] from t 
    59 
    q)res3~res2 
    1b 
+0

編輯了這個問題。克可以有更多的價值比兩個 –

0

可以使用可信賴字典。把你的可能值作爲鍵和作爲值的函數。你甚至可以根據你在表中的鍵值的實際數量動態地生成這個函數。我相信這在性能方面不是最好的。

q)fd:`I`B`C!({(+). [email protected]`a`b};{(+). [email protected]`b`d};{(+). [email protected]`c`d}) 
    q)update r:{(fd x[`g])x}each t from t 
    a b c d g r 
    -------------------- 
    0 10 100 1000 I 10 
    1 11 101 1001 B 1012 
    2 12 102 1002 I 14 
    3 13 103 1003 C 1106 
    4 14 104 1004 B 1018 
    q) 

*編輯 更快的方法,並比較...

q)t:1000000?t 
    q)fd:`I`B`C!({(+). [email protected]`a`b};{(+). [email protected]`c`d};{(+). [email protected]`b`c}) 
    q)\t res1:update r:{(fd x[`g])x}each t from t 
    635 
    q)\t res2:delete idx from`idx xasc raze{[t;idx;it;k] @[d;`idx`r;:;](idxs;(+).(d:t idxs:idx[it])k)}[t;group t`g;]./:flip(`I`C`B;(`a`b;`b`c;`c`d)) 
    79 
    q)res1~res2 
    1b 
    q)