【问题标题】:Call join() on a generator in JS在 JS 中的生成器上调用 join()
【发布时间】:2018-12-17 16:45:42
【问题描述】:

在 Python 中,您可以在任何可迭代对象上调用 string.join() 方法,如下所示:

",".join(some_iterable)

参数可以是列表、生成器或任何其他对象,只要它是可迭代的。

在使用 ES6 时,我无法找到一种方法,而无需先创建一个数组,我不得不这样做:

function *myGenerator() { ... }
let output = [...myGenerator()].join(",");

我知道join() 是一个Array.prototype 方法。我是否可以调用join() 或类似的方法来连接myGenerator 生成的值,而不必像上面的python 示例那样创建中间数组?

【问题讨论】:

  • 如果您愿意,您可以将实现该功能的函数添加到String.prototypejoin;那么您可以致电','.join(myGenerator())。但是在某些时候,您要么必须创建一个数组以使用 that 连接方法,要么编写自己的等价物。在底层,我相信 CPython 等价物 确实 创建了一个中间数组,因为这比创建大量中间字符串更有效。
  • @jonrsharpe 我相信,理论上,您不需要中间数组。如果我的要求目前无法实现,那么这似乎是生成器实现的一个被忽视的功能,不是吗?
  • 不,您不需要 数组,您完全可以编写一个只使用迭代器并构建等效字符串的函数。但这会构建大量的中间 strings,这可能总体上效率较低。无论哪种方式,如果这就是你想写的,是什么阻止你写它?
  • 对您的 literal 问题而不是 spirit 问题的回答是,您可以有一个函数,它接受一个迭代器,对其进行迭代, 在添加分隔符时与字符串连接。
  • @jonrsharpe 你说得对,没有什么能阻止我自己编写它,我只是想知道是否有一个 ES6 功能可以让我像使用 @987654331 一样加入生成器@.

标签: javascript ecmascript-6 generator


【解决方案1】:

上面的 cmets 很好地回答了你的问题。但是,我对@jonrsharpe 关于生成中间字符串的评论感到好奇,并且想知道这实际上是如何影响性能的。所以我在一个生成器的原型上放了一个join 方法并测试了它。

这是join() 代码:

function* nGen(start, stop) {
  while (start < stop) {
    yield start
    start++
  }
}

nGen.prototype.join = function(sep) {
  let res = this.next().value
  for (let v = this.next(); !v.done; v = this.next()) {
    res += sep + v.value
  }
  return res
}


let g = nGen(2, 20)

console.log(g.join(','))

我在 Safari 中的非常非正式的测试表明,这个工作量级比非常常见的习语快几个数量级:[...g].join(',')。在 Chrome 中它更接近,但 join 方法仍然快得多。所以我不确定创建字符串是否会成为真正的瓶颈。

我远不是编写 jsPerf 测试的大师,所以也许我搞砸了一些事情或误解了结果。但如果你有兴趣:https://jsperf.com/generator-join

【讨论】:

  • 是的,在推理中发现了那个愚蠢的错误有点晚了 :) 本末倒置等等……
  • jsPerf 链接好像坏了
猜你喜欢
  • 1970-01-01
  • 2017-05-10
  • 2014-04-23
  • 1970-01-01
  • 2014-11-23
  • 2014-10-28
  • 1970-01-01
  • 2013-01-05
  • 2015-12-02
相关资源
最近更新 更多