编辑:关闭的投票是错误的。 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
的解释,所以我试图避免它。)
答案 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 them)with 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]
。
现在数组中有值,它可以映射,如上所示。
在映射之前,您还可以spread
将array
空undefined
个值转换为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