将 iterable 中的前 N 项转换为数组

问题描述 投票:0回答:5

类似于问题Convert ES6 Iterable to Array。但我只想要前 N 项。有内置的东西可以让我这样做吗?或者我怎样才能更优雅地实现这一目标?

let N = 100;
function *Z() { for (let i = 0; ; i++) yield i; }

// This wont work
// Array.from(Z()).slice(0, N);
// [...Z()].slice(0, N)

// This works, but a built-in may be preferred
let a = [], t = Z(); for (let i = 0; i < N; i++) a.push(t.next().value);
javascript arrays slice infinite iterable
5个回答
8
投票

要获取

n
的第一个
iterator
值,您可以使用以下之一:

Array.from({length: n}, function(){ return this.next().value; }, iterator);
Array.from({length: n}, (i => () => i.next().value)(iterator));

要获取任意

iterator
iterable
,请使用:

const iterator = iterable[Symbol.iterator]();

在你的情况下,给定一个生成器函数

Z

Array.from({length: 3}, function(){ return this.next().value; }, Z());

如果您更频繁地需要此功能,您可以创建一个生成器函数:

function* take(iterable, length) {
  const iterator = iterable[Symbol.iterator]();
  while (length-- > 0) yield iterator.next().value;
}

// Example:
const set = new Set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
console.log(...take(set, 3));


3
投票

没有内置方法可以从可迭代对象中仅获取一定数量的项目(类似于

take()
)。尽管您的代码片段可以通过
for of
循环进行一些改进,该循环专门用于处理可迭代对象,例如:

let a = []; let i = 0; for (let x of Z()) { a.push(x); if (++i === N) break; }

这可能会更好,因为即使可迭代中没有 N 个项目,原始代码片段也会继续循环。


0
投票

使用

.map
会更短,效率会更低,使用自定义函数会更安全:

function *Z() { for (let i = 0; i < 5; ) yield i++; }

function buffer(t, n = -1, a = [], c) { 
    while (n-- && (c = t.next(), !c.done)) a.push(c.value); return a; }

const l = console.log, t = Z()

l( [...Array(3)].map(v => t.next().value) )

l( buffer(t) )


0
投票

我怎样才能更优雅地实现这一点?

一种可能的优雅解决方案,使用 iter-ops 库:

import {pipe, take} from 'iter-ops';

const i = pipe(
    Z(), // your generator result
    take(N) // take up to N values
); //=> Iterable<number>

const arr = [...i]; // your resulting array

附注我是该库的作者。


0
投票

从 ECMAScript 2025 开始,我们有了迭代器助手

take
,所以现在我们可以这样做:

// Example iterable:
const iterable = "StackOverflow"[Symbol.iterator]();

// Get first 5 into array
const arr = iterable.take(5).toArray();
console.log(arr);

// Iterable can still be consumed more (if you wanted to)
console.log(iterable.toArray());

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.