我在kdb数据库上学习Q。我担心q中没有循环的事实。我需要编写一个算法,在像C这样的冗长程序中,我会用几个嵌套的for循环来编写。但在Q中,我被不能循环的事实所困扰。
为了给出一个具体的例子(许多例子中的一个),我有一个简单的向量(列表):
q)closures
price
-----
18.54
18.53
18.53
18.52
18.57
18.9
18.9
18.77
18.59
18.51
18.37我需要一个向量,将这些条目3x3分组,并进行叠加,就像(使用R语法):closures0:2,closures1:3,closures2:4,closures3:5...我该怎么做呢?
一般来说,我需要如何改变我的心态,才能在q中正确编程?
非常感谢你的建议,马可
发布于 2014-08-01 21:40:14
回答你关于“我需要如何改变我的心态,才能在Q中正确编程?”的最后一点:
您需要使用over (/)、scan ()和.z.s,而不是使用循环。
例如,你的问题可以用以下方法来解决:(请注意,对于你的特定问题,这些实际上不是最好的解决方案-索引是更好的方法-但尽管如此,下面的这些解决方案应该有助于理解这一点)
price:18.54 18.53 18.53 18.52 18.57 18.9 18.9 18.77 18.59 18.51 18.37
q)3#'{1_x}\[8;price]
18.54 18.53 18.53
18.53 18.53 18.52
18.53 18.52 18.57
18.52 18.57 18.9
18.57 18.9 18.9
18.9 18.9 18.77
18.9 18.77 18.59
18.77 18.59 18.51
18.59 18.51 18.37也就是说,迭代列表,每次砍掉一个,取每次迭代的前3个
或者类似的
q)3#'{1 rotate x}\[8;price]
18.54 18.53 18.53
18.53 18.53 18.52
18.53 18.52 18.57
18.52 18.57 18.9
18.57 18.9 18.9
18.9 18.9 18.77
18.9 18.77 18.59
18.77 18.59 18.51
18.59 18.51 18.37即旋转1 8次,每次旋转的前3次
使用.z.s方法
q){$[2<count x;enlist[3#x],.z.s 1_x;()]}[price]
18.54 18.53 18.53
18.53 18.53 18.52
18.53 18.52 18.57
18.52 18.57 18.9
18.57 18.9 18.9
18.9 18.9 18.77
18.9 18.77 18.59
18.77 18.59 18.51
18.59 18.51 18.37也就是说,如果至少还有3个元素,取前3个元素,然后砍掉第一个项目,并将相同的功能重新应用于缩短的列表。
在本例中,使用over (/)会令人费解,但一般情况下,over对于替换"while“类型结构很有用
i:0
a:0;
while[i<10;i+:1;a+:10] 更好地实现了使用
q){x+10}/[10;0]
100即,将起始(种子)值为零的10次相加。
b:();
while[not 18~last b;b,:1?20] 也就是说,一直附加1到20之间的随机数,直到你达到18,然后停止。
更好地实现了使用
q){x,1?20}/[{not 18~last x};()]
1 2 16 5 8 18也就是说,在1和20之间附加一个随机数,只要check函数返回true,就进行迭代,以()作为种子值开始
根据你所迭代的函数是一元函数还是二元函数等,还有许多其他的选项可以使用scan和over。
作为一个广义的推广:"for i=1:10“类型的循环可以在Q中使用"function each i”来实现,"do“类型的循环可以在Q中使用"function/numOfTimes;seed”来实现,"while“类型的循环可以在Q中使用"function/booleanCheckFunction;seed”来实现。
发布于 2015-06-11 22:17:27
flip (-2_price;-1_1_price;2_price)正如已经提到的,使用内置总是比使用‘或/迭代更快。这就是为什么在一个有一百万个元素的向量上,从顶部答案开始的代码永远需要花费很长时间才能完成,并且使用了GB的堆。JPC和Harshal的索引方法更快,但上面的翻转更快三倍。
一旦您有了格式的数据,您只需使用each将闭包应用于列表的元素。
始终关注所告诉你的是一个很好的实践- KDB不会为你优化任何东西。
发布于 2013-05-24 20:23:15
至于嵌套循环,我发现创建一个交叉列表是很有用的。E.g
`对于i=1:10
for j=1:20
for k=1:30
f(i, j, k)`
在Q中,您可以
il: 1 _til 11
jl: 1_til 21
kl: 1_til 31
lst: il cross jl cross kl
raze g(x) each til count ls其中g定义为
g: {[i]
itr: first lst[i];
jtr: first 1_lst[i];
ktr: last lst[i];
f(itr, jtr, ktr)
}希望这能澄清。至于闭包部分,我不知道那里的R语法。如果你能说出你想要什么输出,你可以帮上忙。
https://stackoverflow.com/questions/16730393
复制相似问题