最近在写一个 Code Review Agent,有下面一段代码:
js
const available_files = file_index
.keys()
.filter((k) => k !== file.path)
const decision_prompt = `${build_followup_prompt(file.path, findings, available_files)}
--- Tool Results ---
${context_addendum}
Based on these results, what's your next action?`
解释:
build_followup_prompt接受当前需要 Review 的文件和首轮已经被 Agent Review 过后的 findings(发现的问题)以及除了自身之外的其他文件,然后总结成一段提示词,进入 loop:让 Agent 决策是结束还是使用工具(cat / grep / find......)还是用 skill(security-audit / performance-review /...)继续 Review。
但现在的代码有问题 build_followup_prompt 接受的 available_files 是字符串数组。然而 file_index 是 Map,keys() 后变成 Iterator 然后被 filter,过后仍然是 Iterator。
故需要将 Iterator 转成 Array。
如果按照过往经验,我这个时候会使用 Array.from 或者更简洁的扩展操作符 [...]。
但是我今天突发奇想,有没有 toArray 方法?
diff
const available_files = file_index
.keys()
.filter((k) => k !== file.path)
+ .toArray()
还真有,既然我不知道肯定有更多人不知道,故今天分享下 toArray()
题外话:
toArray和 rs 的collect非常相似:
rslet available_files: Vec<&str> = file_index .keys() .filter(|&&k| k != file.path) .copied() .collect(); // ←
下面内容来自 MDN。
iterator.toArray
迭代器(Iterator)实例的 toArray() 方法会创建一个全新数组(Array),并将迭代器产出的所有元素填充至该数组中。
js
toArray()
返回值
一个全新数组实例,按迭代器元素的产出顺序存放所有迭代项。
示例
iterator.toArray() 效果等同于 Array.from(iterator) 与扩展运算符写法 [...iterator],优势在于链式调用多个迭代器工具方法时代码更简洁。
下面示例生成一个输出斐波那契数列的迭代器,取出前 10 项、过滤掉奇数,最后转为数组:
js
function* fibonacci() {
let current = 1;
let next = 1;
while (true) {
yield current;
[current, next] = [next, current + next];
}
}
const array = fibonacci()
.take(10)
.filter((x) => x % 2 === 0)
.toArray();
console.log(array); // [2, 8, 34]
注意:建议将 toArray() 作为数据处理的最后一步。
反例:fibonacci().take(10).toArray().filter(...) 效率更低,因为迭代器工具方法采用惰性求值,能省去中间临时数组的创建开销。
兼容性
Node.js v22、Chrome v122
平常写 CLI 够用了
扩展
除了 toArray filter 还有哪些 iterator helper methods 呢?全部都在这:
forEachsome/everymap/flatMap/reducefind/includesdrop/take
可见基本和数组类似,多了 drop / take。