首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >KDB/Q:如何在没有循环的情况下进行循环?

KDB/Q:如何在没有循环的情况下进行循环?
EN

Stack Overflow用户
提问于 2013-05-24 16:07:21
回答 7查看 13K关注 0票数 8

我在kdb数据库上学习Q。我担心q中没有循环的事实。我需要编写一个算法,在像C这样的冗长程序中,我会用几个嵌套的for循环来编写。但在Q中,我被不能循环的事实所困扰。

为了给出一个具体的例子(许多例子中的一个),我有一个简单的向量(列表):

代码语言:javascript
复制
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中正确编程?

非常感谢你的建议,马可

EN

回答 7

Stack Overflow用户

发布于 2014-08-01 21:40:14

回答你关于“我需要如何改变我的心态,才能在Q中正确编程?”的最后一点:

您需要使用over (/)、scan ()和.z.s,而不是使用循环。

例如,你的问题可以用以下方法来解决:(请注意,对于你的特定问题,这些实际上不是最好的解决方案-索引是更好的方法-但尽管如此,下面的这些解决方案应该有助于理解这一点)

代码语言:javascript
复制
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个

或者类似的

代码语言:javascript
复制
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方法

代码语言:javascript
复制
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“类型结构很有用

代码语言:javascript
复制
i:0
a:0;
while[i<10;i+:1;a+:10] 

更好地实现了使用

代码语言:javascript
复制
q){x+10}/[10;0]
100

即,将起始(种子)值为零的10次相加。

代码语言:javascript
复制
b:();  
while[not 18~last b;b,:1?20]      

也就是说,一直附加1到20之间的随机数,直到你达到18,然后停止。

更好地实现了使用

代码语言:javascript
复制
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”来实现。

票数 10
EN

Stack Overflow用户

发布于 2015-06-11 22:17:27

代码语言:javascript
复制
flip (-2_price;-1_1_price;2_price)

正如已经提到的,使用内置总是比使用‘或/迭代更快。这就是为什么在一个有一百万个元素的向量上,从顶部答案开始的代码永远需要花费很长时间才能完成,并且使用了GB的堆。JPC和Harshal的索引方法更快,但上面的翻转更快三倍。

一旦您有了格式的数据,您只需使用each将闭包应用于列表的元素。

始终关注所告诉你的是一个很好的实践- KDB不会为你优化任何东西。

票数 3
EN

Stack Overflow用户

发布于 2013-05-24 20:23:15

至于嵌套循环,我发现创建一个交叉列表是很有用的。E.g

`对于i=1:10

代码语言:javascript
复制
 for j=1:20
    for k=1:30
      f(i, j, k)

`

在Q中,您可以

代码语言:javascript
复制
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定义为

代码语言:javascript
复制
g: {[i]
itr: first lst[i];
jtr: first 1_lst[i];
ktr: last lst[i];

f(itr, jtr, ktr)
}

希望这能澄清。至于闭包部分,我不知道那里的R语法。如果你能说出你想要什么输出,你可以帮上忙。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16730393

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档