解决你关于“我需要如何改变心态,以正确地在 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 八次,每次旋转前 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 之间的随机数,只要检查函数返回 true 就进行迭代,以 () 作为种子值开始
还有许多其他选项可以使用 scan 和 over,具体取决于您要迭代的函数是 monadic/diadic 等。
作为一个广泛的概括:
使用“function each i”可以在 q 中实现“for i=1:10”类型的循环,
可以使用“function/[numOfTimes;seed]”在 q 中实现“do”类型的循环,
使用“function/[booleanCheckFunction;seed]”可以在 q 中实现“while”类型的循环