ES6 - 生成一个数字数组

72

我在谷歌上搜索后找到了两种解决方案:

    var data = [...Array(10).keys()];
console.log(data);
    var data1 = Array(8).fill().map((_, i) => i);
console.log(data1);

data1显示[0, 1, ..., 7],但数据只显示[[object Array Iterator]],如何实际查看数字。

我需要它对数字进行一些迭代(作为Euler项目的一部分)。

之前我在Python中做了很多Euler挑战。现在我决定重新访问它,并尽可能多地使用JS(尽可能使用ES6语法)来帮助我开发我的js技能。


3
如果我在我的浏览器(最新稳定版的Chrome)中运行var data = [...Array(10).keys()];,我会看到数字被列出。如果只执行Array(10).keys(),我会看到 ArrayIterator。请翻译以上内容。 - Mike Cluck
1
这与CodePen有关吗?http://codepen.io/wasteland/pen/QKQGNo/?editors=1111 - Wasteland
2
@Wasteland 这与 Babel 有关,它正在特定的代码笔记中使用。 - Madara's Ghost
2
这与CodePen使用Babel有关。我不确定他们正在运行哪个版本,但如果禁用Babel预处理器,一切都将正确。您可以在Babel网站上运行此代码,并且仍将看到您期望的结果。 - Mike Cluck
谢谢。ES6功能需要Babel吗? - Wasteland
6个回答

142

以下是一个在CodePen中有效的简单解决方案:

Array.from(Array(10).keys())

要明确的是,Array.from()Array.keys()需要使用ES6 polyfill才能在所有浏览器中使用。


21
更好的写法:[...Array(10).keys()] - vsync

75

通过实际例子了解 Array.from 方法

Array.from 还接受第二个参数作为映射函数。

let out = Array.from(Array(10), (_,x) => x);
console.log(out);
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

这很有用,因为您可能希望生成比0N更复杂的数组。

const sq = x => x * x;
let out = Array.from(Array(10), (_,x) => sq(x));
console.log(out);
// [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

您也可以使用生成器创建数组

function* range(start, end, step) {
  while (start < end) {
    yield start;
    start += step;
  }
}

let out = Array.from(range(10,20,2));

console.log(out); // [10, 12, 14, 16, 18]

Array.from非常强大,人们甚至还没有完全意识到它的潜力。

const ord = x => x.charCodeAt(0);
const dec2hex = x => `0${x.toString(16)}`.substr(-2);

// common noob code
{
  let input = "hello world";
  let output = input.split('').map(x => dec2hex(ord(x)));
  
  console.log(output);
  // ["68", "65", "6c", "6c", "6f", "20", "77", "6f", "72", "6c", "64"]
}

// Array.from
{
  let input = "hello world";
  let output = Array.from(input, x => dec2hex(ord(x)));
  
  console.log(output);
  // ["68", "65", "6c", "6c", "6f", "20", "77", "6f", "72", "6c", "64"]
}


2
那个“noob code”有什么问题吗?我认为它更易读。 - Quelklef

38

看起来问题在于CodePen使用babel es2015-loose预编译您的代码。

在这种模式下,您的

[...Array(10).keys()];

变成

[].concat(Array(10).keys());

这就是为什么你会看到一个包含迭代器的数组。

在ES2015模式下,您将获得

function _toConsumableArray(arr) {
  if (Array.isArray(arr)) {
    for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {
      arr2[i] = arr[i];
    }
    return arr2;
  } else {
    return Array.from(arr);
  }
}
[].concat(_toConsumableArray(Array(10).keys()));

将会按预期运行。

有关这些模式的更多信息,请参见②ality - Babel 6:松散模式


36

这里的所有其他答案都创建了一个临时中间数组,这并非必要。

Array.from({ length: 10 }, (_, i) => i)

这本质上是一个映射函数,您可以将其从数组索引映射到任何您想要的东西,适用于任何数量的元素。


2
这绝对是最优雅的方法,也很可能是最高效的方法,使用一个具有长度属性的对象来充当可迭代对象,并将map函数集成在同一个“循环”中。 - Jax Cavalera

21
进一步改进,生成一个以1为起始值的数组:
Array.from(Array(10).keys(), n => n + 1)

11

这里是一个 range 函数,它接受 startendstep 参数。它返回一个数组,从 start 开始,按大小为 step 的增量增加,直到(但不包括)end 数字。

const range = (start, end, step) => {
  return Array.from(Array.from(Array(Math.ceil((end-start)/step)).keys()), x => start+ x*step);
}

console.log(range(1, 10, 1));
//[1, 2, 3, 4, 5, 6, 7, 8, 9]

console.log(range(0, 9, 3));
//[0, 3, 6]

console.log(range(10, 30, 5));
//[10, 15, 20, 25]

如果你想要一个包含 end 的范围,可以进一步采取以下步骤。

const inclusiveRange = (start, end, step) => {
  return Array.from(Array.from(Array(Math.ceil((end-start+1)/step)).keys()), x => start+ x*step);
}

console.log(inclusiveRange(1, 10, 1));
//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

console.log(inclusiveRange(0, 9, 3));
// [0, 3, 6, 9]

console.log(inclusiveRange(10, 30, 5));
//[10, 15, 20, 25, 30]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接