成语为“重复n次”?

时间:2013-08-28 23:27:29

标签: javascript


编辑:关闭的投票是错误的。 Repeat Character N Times中接受的答案一般不适用。 E.g:

>>> Array(3).map(Math.random)
[undefined, undefined, undefined]

另外两个答案建议修改一个内置类,这种做法我认为是完全不可接受的。


这是在JS中生成3个随机数的数组有点浪费且不切实际的方法:

>>> [1, 1, 1].map(Math.random)
[0.6324464592887568, 0.5969209806782131, 0.7362755801487572]

使用虚拟数组(例如[1, 1, 1])以便可以在其上调用map,对于足够大的 n 来说都是浪费(内存)并且不切实际。

人们想要的是一个假设的东西:

>>> repeat(3, Math.random)
[0.21425955396598173, 0.00226050232425945, 0.45261888146445495]

“纯JS”中最接近的是什么?

(我知道Underscore,但是它的API中的内容对我来说没有意义,例如对map的解释,所以我试图避免它。)

6 个答案:

答案 0 :(得分:42)

可以使用Array.prototype.map完成,但数组不能为空。首先Fill

console.log(
    Array(3).fill().map(Math.random)
);

<强>解释

new Array(3)构造函数会创建a sparse array(或"holey" array, as the V8 team calls themwith three holes in it and a length of three。这意味着它等同于[,,,],它会创建[<empty>, <empty>, <empty>,](注意JavaScript的trailing commas)。

Array.prototype.map被称为once for each element in the array。但是,因为空数组没有赋值,所以根本不会调用回调。例如,[1,,2].map(v=>v*2)会给[2,,4];中间位置被跳过。

输入Array.prototype.fill(value, start?, end?):只有一个参数,它用指定的值填充数组中的每个插槽。从技术上讲,第一个参数不是可选的,但通过省略它,undefined用作值。这没关系,因为无论如何都没有使用该值。这种方式Array(3).fill()为我们提供了[undefined, undefined, undefined]

现在数组中有值,它可以映射,如上所示。

在映射之前,您还可以spreadarrayundefined个值转换为console.log( [...Array(3)].map(Math.random) );

Array.prototype.map

<强>解释

ECMAScript2015或更新threat holes in arrays as undefined values中引入的数组运算符。 ...是在ES5(IE what preceded ES2015)中引入的,其中令人困惑的是,数组中的漏洞将被跳过,在JS Array函数中产生一些不一致性,具体取决于它们发布的ECMAScript版本英寸

点差运算符undefined was introduced in ES2015,根据规范,它会将给定数组中的任何空洞转换为[...Array(3)]的值。换句话说,[undefined, undefined, undefined]给了我们Array(3).fill(),就像Array.prototype.map上面所做的那样。

有时您可能需要按顺序播种数字。正如Kevin Danikowski所指出的那样,const Fibonacci = n => Math.round(((5**.5 + 1) / 2)**n / 5**.5); console.log( Array(10).fill().map((_, i) => Fibonacci(++i)) );提供了开箱即用的功能,因为第二个参数是当前密钥:

{{1}}

答案 1 :(得分:36)

Underscore.js有一个times函数,可以完全按照您的要求执行:

_.times(3, Math.random)

如果您不想使用Underscore,您可以编写自己的times函数(从Underscore源复制并略微简化):

times = function(n, iterator) {
  var accum = Array(Math.max(0, n));
  for (var i = 0; i < n; i++) accum[i] = iterator.call();
  return accum;
};

答案 2 :(得分:15)

最短的优雅ES6:

let times=(n,f)=>{while(n-->0)f();}

哦,那不是用于创建阵列,但它仍然很整洁!

times(3,()=>print('wow'))

或Ruby风格:

Object.assign(Number.prototype,{times(f){x=this;while(x-->0)f();}})
3..times(()=>print('wow'))

答案 3 :(得分:14)

也许Array.from回调可能有用:

var result = Array.from(Array(3), Math.random);

console.log(result);

使用map比使用map略有优势:fill已经需要一个带有所有条目的数组(可能是使用map创建的,或者是扩展语法),然后从那里创建最终的数组。总的来说,Array.from解决方案将创建 n 条目两次length不需要包含条目的数组,只需要具有Array(3)属性的对象,var result = Array.from({length:3}, Math.random); console.log(result);即可提供。

因此,根据您的偏好,上述内容也可以这样做:

repeat

最后,如果要为此创建length函数,可以将参数命名为const repeat = (length, cb) => Array.from({length}, cb); const result = repeat(3, Math.random); console.log(result);并使用ES6短符号表示对象文字:

yrange

答案 4 :(得分:3)

我喜欢这样:

[...Array(5).keys()].forEach(index =>
  console.log(`do something ${index}`
)

答案 5 :(得分:2)

创建repeat函数的现代方法:

repeat = (n, cb) => {[...Array(n)].forEach(cb)}

然后您可以将其用于:

repeat(3, _ => console.log(Math.random()))

输出:

0.6324464592887568
0.5969209806782131
0.7362755801487572