Skip to main content

用递归遍历列表并追加序号

2 min read

接口需要按原有顺序逐条处理记录,并给每条数据追加从 0 开始的 seq_no。DataQL 可以用递归函数表达这个过程。

输入与目标​

把以下 JSON 作为查询参数传入,脚本通过 ${参数名} 读取。

查询参数
{
"rows": [
{
"name": "Alice"
},
{
"name": "Bob"
}
]
}

实现过程​

append 接收列表、结果容器和当前位置。index 小于列表长度时处理当前行,再把 index + 1 交给下一次调用;到达末尾后返回容器。newList 在递归外只创建一次,各层把结果追加到同一列表。

import 'net.hasor.dataql.host.function.basic.CollectionUdfSource' as collect;
var append = (rows, output, index) -> {
if (index < collect.size(rows)) {
run output.addLast(collect.mergeMap(rows[index], {'seq_no': index}));
run append(rows, output, index + 1);
}
return output;
};
return append(${rows}, collect.newList(), 0).data();

执行结果​

[
{
"name": "Alice",
"seq_no": 0
},
{
"name": "Bob",
"seq_no": 1
}
]

列表为空时直接返回 [],不会读取下标 0。这个写法适合说明按位置处理的流程;普通字段变换优先使用列表转换表达式,较长列表避免逐行递归带来的调用栈增长。

运行源码​

完整示例工程包含 Java 入口、脚本、参数和预期结果;本篇文件位于 cases/like-for。

mvn -f example/dataql-blog-example/pom.xml compile exec:java -Dexec.args=like-for

执行 mvn -f example/dataql-blog-example/pom.xml test 可核对八篇文章的结果。查询入口使用 HostConfiguration → QueryManager → QueryBuilder,不需要启动 Web 服务。通过 Dataway 运行时,在 Parameters 面板填入同一份参数,选择 Raw Value 查看本文的原始结果。