如何从参数列表中将 Q 函数调用重组为字符串?
How can I recompose a Q function call as a string from a list of arguments?
我正在使用 C# 使用 KX 提供的 c.cs
库对 KDB 数据库执行 q 代码。我以对象(整数、字符串、Dict 实例等)的形式向该库中的 c.k
方法提供参数,这一切都很好。但是,当我有一个使用此方法不起作用的查询时,我总是想做的是获取我刚刚通过 C# 适配器执行的查询并在 Q 控制台中重新执行它,以便我可以修改它并找出我做错了什么。问题是,在 C# 环境中,我将 Q 函数的参数作为参数(在某些情况下,有些复杂的基于字典的参数树),手动将我的参数转换为 func[arg1;arg2;arg3...];
期望的格式真的很痛苦Q 控制台。我真正希望能够做的是将我的参数传递给一个函数,该函数将以一种语法重组原始查询,使我能够轻松地在控制台中重新执行原始查询。像这样:
在 C# 中
var client = new c();
[connect]
var funcName = "myFunc";
var arg1 = "test";
var arg2 = 12345;
var arg3 = new c.Dict(new [] { "a", "b" }, new [] { true, false });
try {
var result = c.k(funcName, arg1, arg2, arg3);
} catch {
var composedStatement = c.k("getComposedStatement", funcName, new[] { arg1, arg2, arg3 });
// composedStatement: "myFunc[`test;12345i;`a`b!10b];"
Logger.LogError("KDB Query failed: " + composedStatement);
}
在Q
getComposedStatement:{[funcName;arguments]
:(string funcName),"[",(qWizardryGoesHere arguments),"];";
}
希望这很清楚我要实现的目标。重要的是 getComposedStatement
函数有一个函数名,以及一个 任意 个可以是任何类型的参数,包括嵌套类型(列表的列表,列表的列表)字典,不同类型的字典等)和returns一个可以直接复制并粘贴到Q控制台中执行的语句。
我认为这就是您在 kdb 函数中查找的内容。
使用 .Q.s1
获取每个参数的字符串表示,然后使用 sv
获取参数的 ;
分隔字符串。还有一些额外的位来创建 .
/ @
apply:
getComposedStatement:{
// conditional to create a . or @ apply depending on number of parameters
// @ apply will only work with 1 parameter
$[1 < count y;".";"@"],
"[`",x,";(",(";" sv .Q.s1 each y),")]"
}
有用的链接:
https://code.kx.com/q/ref/dotq/#qs1-string-representation
https://code.kx.com/q/ref/apply/
编辑:帮助您在 q 中调试的更好方法是完全避免基于字符串的解决方案并创建一个调试变量。然后您可以在 q 控制台中获得函数和参数,可以是 运行 和 eval .debug
createDebug:{
// simply create a list with function name and parameters
// assign it to the .debug namespace so it is available
// outside of the function call.
.debug:(,/)enlist each x,y;
}
testFunc:{1 2 3!(x;y;z)}
createDebug[`testFunc;("test";12345i;`a`b!10b)]
show .debug
(`testFunc;"test";12345;(`a`b)!10b)
eval .debug
key value
1 "test"
2 12345
3 (`a`b)!10b
编辑 2:
由于 OP 在处理超过 2000 个字符的对象时遇到问题,另一种方法是使用 JSON。我不确定这将如何在 C# 中处理,但值得一试。
getComposedStatement:{
(x;.j.j each y)
}
// 3rd arg is a very large dictionary
getComposedStatement[`testFunc;("test";12345i;(til 2000)!2000?`3)]
(`testFunc;(""test"";"12345";{"0":"gia","1":"dmj","2":"pnh","3":"ofc","4":"hon","5":"jjb", ...
然后您必须在另一端使用 运行 函数将 json 转换回:
runComposedStatement:{
eval (first x),.j.k each last x
}
runComposedStatement[getComposedStatement[`testFunc;("test";12345i;(til 2000)!2000?`3)]]
(1j, 2j, 3j)!("test";12345f;(`0`1`2`3`4`5`6`7`8`9`10`11`12`13`14`15 ...
我不想 post 整个词典,但我确认它是完整的。希望这可以实现您想要的或至少更近一步。可能需要更多来处理 JSON.
我正在使用 C# 使用 KX 提供的 c.cs
库对 KDB 数据库执行 q 代码。我以对象(整数、字符串、Dict 实例等)的形式向该库中的 c.k
方法提供参数,这一切都很好。但是,当我有一个使用此方法不起作用的查询时,我总是想做的是获取我刚刚通过 C# 适配器执行的查询并在 Q 控制台中重新执行它,以便我可以修改它并找出我做错了什么。问题是,在 C# 环境中,我将 Q 函数的参数作为参数(在某些情况下,有些复杂的基于字典的参数树),手动将我的参数转换为 func[arg1;arg2;arg3...];
期望的格式真的很痛苦Q 控制台。我真正希望能够做的是将我的参数传递给一个函数,该函数将以一种语法重组原始查询,使我能够轻松地在控制台中重新执行原始查询。像这样:
在 C# 中
var client = new c();
[connect]
var funcName = "myFunc";
var arg1 = "test";
var arg2 = 12345;
var arg3 = new c.Dict(new [] { "a", "b" }, new [] { true, false });
try {
var result = c.k(funcName, arg1, arg2, arg3);
} catch {
var composedStatement = c.k("getComposedStatement", funcName, new[] { arg1, arg2, arg3 });
// composedStatement: "myFunc[`test;12345i;`a`b!10b];"
Logger.LogError("KDB Query failed: " + composedStatement);
}
在Q
getComposedStatement:{[funcName;arguments]
:(string funcName),"[",(qWizardryGoesHere arguments),"];";
}
希望这很清楚我要实现的目标。重要的是 getComposedStatement
函数有一个函数名,以及一个 任意 个可以是任何类型的参数,包括嵌套类型(列表的列表,列表的列表)字典,不同类型的字典等)和returns一个可以直接复制并粘贴到Q控制台中执行的语句。
我认为这就是您在 kdb 函数中查找的内容。
使用 .Q.s1
获取每个参数的字符串表示,然后使用 sv
获取参数的 ;
分隔字符串。还有一些额外的位来创建 .
/ @
apply:
getComposedStatement:{
// conditional to create a . or @ apply depending on number of parameters
// @ apply will only work with 1 parameter
$[1 < count y;".";"@"],
"[`",x,";(",(";" sv .Q.s1 each y),")]"
}
有用的链接:
https://code.kx.com/q/ref/dotq/#qs1-string-representation
https://code.kx.com/q/ref/apply/
编辑:帮助您在 q 中调试的更好方法是完全避免基于字符串的解决方案并创建一个调试变量。然后您可以在 q 控制台中获得函数和参数,可以是 运行 和 eval .debug
createDebug:{
// simply create a list with function name and parameters
// assign it to the .debug namespace so it is available
// outside of the function call.
.debug:(,/)enlist each x,y;
}
testFunc:{1 2 3!(x;y;z)}
createDebug[`testFunc;("test";12345i;`a`b!10b)]
show .debug
(`testFunc;"test";12345;(`a`b)!10b)
eval .debug
key value
1 "test"
2 12345
3 (`a`b)!10b
编辑 2:
由于 OP 在处理超过 2000 个字符的对象时遇到问题,另一种方法是使用 JSON。我不确定这将如何在 C# 中处理,但值得一试。
getComposedStatement:{
(x;.j.j each y)
}
// 3rd arg is a very large dictionary
getComposedStatement[`testFunc;("test";12345i;(til 2000)!2000?`3)]
(`testFunc;(""test"";"12345";{"0":"gia","1":"dmj","2":"pnh","3":"ofc","4":"hon","5":"jjb", ...
然后您必须在另一端使用 运行 函数将 json 转换回:
runComposedStatement:{
eval (first x),.j.k each last x
}
runComposedStatement[getComposedStatement[`testFunc;("test";12345i;(til 2000)!2000?`3)]]
(1j, 2j, 3j)!("test";12345f;(`0`1`2`3`4`5`6`7`8`9`10`11`12`13`14`15 ...
我不想 post 整个词典,但我确认它是完整的。希望这可以实现您想要的或至少更近一步。可能需要更多来处理 JSON.