鉴于以下内容。我想懒惰地将transform
应用于从Object.keys
返回的可迭代的每个成员。
我该怎么做?
function* numbers(upto, transform) {
yield* Object.keys([...Array(upto)]); // How can `transform` be applied here lazily?
}
function timesTwo(n) {
return n*2;
}
var generator = numbers(31, timesTwo)
for(var i of generator) {
console.log(i); // 0 2 4 6 8... 60
}
答案 0 :(得分:5)
由于您很高兴将转换传递到numbers
,因此如果您利用numbers
作为生成器,则可以在生成时应用它:
function* numbers(upto, transform) {
let n = 0;
while (n < upto) {
yield transform(n);
++n;
}
}
const timesTwo = n => n * 2;
const generator = numbers(31, timesTwo);
for (const i of generator) {
console.log(i); // 0 2 4 6 8... 60
}
Live on Babel's REPL适用于那些浏览器无法运行上述内容的人。
我们可以使用numbers
的原始定义,但我们要么急切地应用变换而不是懒惰,要么我们必须使用数组的迭代器(无论如何都会一次创建数组。这是后一个:
function* numbers(upto, transform) {
for (const n of Object.keys([...Array(upto)])) {
yield transform(n);
}
}
const timesTwo = n => n * 2;
const generator = numbers(31, timesTwo);
for (const i of generator) {
console.log(i); // 0 2 4 6 8... 60
}
我们可以将numbers
的两个方面分开,并且具有通用transform
函数,该函数基本上是map
的生成器版本:
function* transform(iterable, f) {
for (const v of iterable) {
yield f(v);
}
}
然后我们可以在更基本的numbers
上使用它:
function* transform(iterable, f) {
for (const v of iterable) {
yield f(v);
}
}
function* numbers(upto) {
yield* Object.keys([...Array(upto)]);
}
const timesTwo = n => n * 2;
const generator = transform(numbers(31), timesTwo);
for (const i of generator) {
console.log(i); // 0 2 4 6 8... 60
}
旁注:我确定你知道这一点,但是对于任何潜伏者来说,问题中的numbers
[及其中的几个]会迭代一系列字符串:"0"
,"1"
等。但是当我们与它们相乘时,它们会被强制转换为数字。要根据问题的numbers
方法实际获得一系列数字,我们需要
yield* Object.keys([...Array(upto)]).map(Number));
答案 1 :(得分:1)
function lazy(f) {
return function*(iter) {
for(const v of iter) {
yield f(v);
}
}
}
function* numbers(upto, transform) {
yield* lazy(transform)(Object.keys([...Array(upto)]));
}
function timesTwo(n) {
console.log('times two called on ', n);
return n*2;
}
var generator = numbers(11, timesTwo)
for(var i of generator) {
console.log(i); // 0 2 4 6 8... 20
}