79

以下は、JS で 3 つの乱数の配列を生成する、やや無駄が多く非現実的な方法です。

[1, 1, 1].map(Math.random) // Outputs: [0.63244645928, 0.59692098067, 0.73627558014]

ダミー配列 (例: [1, 1, 1]) を呼び出すことができるようにするためだけにダミー配列を使用することは、 nmapが十分に大きい場合、(メモリの) 無駄が多く、実用的ではありません。

希望するものは、仮説のようなものです。

repeat(3, Math.random) // Outputs: [0.214259553965, 0.002260502324, 0.452618881464]

バニラ JavaScript を使用してできる最も近いものは何ですか?

Underscore のようなライブラリは認識していますが、ここではライブラリを避けようとしています。

Repeat a string a number timesの回答を見ましたが、一般的には当てはまりません。例えば:

Array(3).map(Math.random) // Outputs: [undefined, undefined, undefined]
Array(4).join(Math.random()) // Outputs a concatenation of a repeated number
Array(3).fill(Math.random()) // Fills with the same number

他のいくつかの回答では、組み込みクラスの変更が提案されています。私が完全に容認できないと考える慣習。

4

7 に答える 7

130

を使用して実行できArray.prototype.mapますが、配列を空にすることはできません。最初に入力してください:

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

説明:

new Array(3)コンストラクターは、3 つの穴と長さ 3を持つスパース配列(または、V8 チームが呼ぶ「穴あき」配列)を作成します。これは、 (JavaScript の末尾のカンマに注意してください) を作成する と同等であることを意味します。空のスロット、つまり穴は、割り当てられた値と同じではないことに注意してください。は実際の値ですが、は配列内の単なるギャップです。[,,,][<empty>, <empty>, <empty>,]undefinedundefined<empty>

Array.prototype.map配列内の要素ごとに 1 回呼び出されます。ただし、空の配列には値が割り当てられていないため、コールバックはまったく呼び出されません。たとえば、次のように[1,,2].map(v=>v*2)なります[2,,4]。中央のスロットにはギャップがあるため、スキップされます。

Enter Array.prototype.fill(value, start?, end?): 引数を 1 つだけ指定すると、配列内のすべてのスロットが指定された値で埋められます。技術的には、最初のパラメータはオプションではありませんが、省略しundefinedて値として使用されます。とにかく値が使用されていないため、これは問題ありません。このようにしArray(3).fill()て、 が得られ[undefined, undefined, undefined]ます。

配列に値が含まれるようになったので、上記のようにマップできます。


マッピングする前に値をspread空にすることもできます:arrayundefined

console.log(
    [...Array(3)].map(Math.random)
);

説明:

ECMAScript2015 以降で導入された配列演算子は、配列の穴をundefinedとして扱います。Array.prototype.mapは ES5 (IEは ES2015 に先行するもの) で導入されましたが、混乱を招くことに、配列の穴はスキップされ、リリースされた ECMAScript のエディションに応じて JS 配列関数に少し矛盾が生じます。

スプレッド演算子... は ES2015で導入されたため、仕様に従って、指定された配列の穴を の値に変換しますundefined。言い換えると、上記と同じように が[...Array(3)]得られます。[undefined, undefined, undefined]Array(3).fill()


場合によっては、順番に数をシードする必要がある場合があります。Kevin Danikowskiが指摘したArray.prototype.mapように、2 番目のパラメーターが現在のキーであるため、すぐに使用できます。

const Fibonacci = n => Math.round(((5**.5 + 1) / 2)**n / 5**.5);

console.log(
    Array(10).fill().map((_, i) => Fibonacci(++i))
);

于 2017-02-17T19:42:39.903 に答える
40

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;
};
于 2013-08-28T23:37:02.687 に答える
24

最短のエレガントな 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'))
于 2015-11-07T18:04:02.047 に答える
24

コールバックが役に立つかもしれませArray.fromん:

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

console.log(result);

ここでは、 を使用するよりもわずかな利点があります。すべてのエントリ(またはスプレッド構文で作成された可能性があります) を含む配列が既に必要であり、そこから最終的な配列を作成しmapますmap。したがって、合計で、ソリューションはn 個のエントリを 2 回作成します。エントリを持つ配列は必要ありません。プロパティを持つオブジェクトだけで十分であり、それを提供しています。fillmapArray.fromlengthArray(3)

したがって、好みに応じて、上記を次のように行うこともできます。

var result = Array.from({length:3}, Math.random);

console.log(result);

最後に、repeatこのための関数を作成する場合は、引数に名前を付けて、lengthオブジェクト リテラルに ES6 短縮表記を使用できます。

const repeat = (length, cb) => Array.from({length}, cb);

const result = repeat(3, Math.random);
console.log(result);

于 2016-11-07T20:33:56.293 に答える