2016-12-28 77 views
3

给出以下内容。我想懒惰地将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

那'transform'参数使得它看起来就像你很高兴有转换传入“数字”而不是从外部编写它们,这是否正确? –

+0

是的。 – Ben

+1

正试图创建一个简单的例子,但可能错过了一些东西。发展我在这方面的理解...IIUC'yield *'意味着内部'iterable'的每个值都被产生。据我所知,这符合一个简单的例子。我会想象一个真实的例子可能是一个数字太大而不适合内存的列表。 – Ben

回答

4

既然你是高兴有变换传入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 
 
}

Live on Babel's REPL


我们可以分离出的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 
 
}

On Babel's REPL


附注:我敢肯定,你知道这一点,但对于任何观望者,在问题numbers [和他们夫妇下文]迭代一系列"0","1"等。但是,当我们与他们相乘时,他们被强迫数字。要真正有一系列基于问题的numbers方式的数字,我们需要

yield* Object.keys([...Array(upto)]).map(Number)); 
+0

大概如果我想要一个懒惰转换我需要构建一个新的迭代,在该变换懒惰地执行的代表团。 – Ben

+0

@BenAston:的确如此。这就是我在上面的第二个例子中所做的,然后我回到了第三个分支。 –

0

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 
 
}