1からNまでを含むJavaScript配列を作成するための以下の代替手段を探しています。Nは実行時にのみ認識されます。
var foo = [];
for (var i = 1; i <= N; i++) {
foo.push(i);
}
私には、ループなしでこれを行う方法があるはずだと感じています。
1 ... N
か?
1からNまでを含むJavaScript配列を作成するための以下の代替手段を探しています。Nは実行時にのみ認識されます。
var foo = [];
for (var i = 1; i <= N; i++) {
foo.push(i);
}
私には、ループなしでこれを行う方法があるはずだと感じています。
1 ... N
か?
回答:
私があなたが何を求めて1..n
いるかがわかった場合、後でループできる数値の配列が必要です。
これで十分な場合は、代わりにこれを実行できますか?
var foo = new Array(45); // create an empty array with length 45
次に、それを使用したい場合...(たとえば、最適化されていない)
for(var i = 0; i < foo.length; i++){
document.write('Item: ' + (i + 1) + ' of ' + foo.length + '<br/>');
}
たとえば、配列に何も格納する必要がない場合は、反復できる適切な長さのコンテナーが必要なだけです...これは簡単かもしれません。
ここで実際にそれを見てください:http : //jsfiddle.net/3kcvm/
var n = 45;
、次にループする1..n
ことで十分です。
foo.length = M
---カットオフ情報が失われることに注意してください。実際の動作を見る==> jsfiddle.net/ACMXp
var n = 45;
。
new Array(45);
「45要素の配列を作成する」ことはできません(同じ意味で[undefined,undefined,..undefined]
)。むしろ、「長さ= 45の空の配列を作成する」([undefined x 45]
)と同じvar foo = []; foo.length=45;
です。そのためforEach
、map
この場合は適用されません。
ES6では、Array from()およびkeys()メソッドを使用します。
Array.from(Array(10).keys())
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
スプレッド演算子を使用した短いバージョン。
[...Array(10).keys()]
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
map
ます。値([...Array(10).keys()].map(x => x++);
)を調整して1から始めるには、配列にaをチェーンする必要があります
map(x => x++)
するだけmap(x => ++x)
です:)
map
簡単にできるのですslice
か? [...Array(N+1).keys()].slice(1)
keys
せずに1つのマップのみ->Array.from(Array(10)).map((e,i)=>i+1)
from
Array.from(Array(10), (e,i)=>i+1)
あなたはそうすることができます:
var N = 10;
Array.apply(null, {length: N}).map(Number.call, Number)
結果:[0、1、2、3、4、5、6、7、8、9]
またはランダムな値で:
Array.apply(null, {length: N}).map(Function.call, Math.random)
結果:[0.7082694901619107、0.9572225909214467、0.8586748542729765、0.8653848143294454、0.008339877473190427、0.9911756622605026、0.8133423360995948、0.8377588465809822、0.5577575915958732、0.16363654541783035]
まず、これNumber.call(undefined, N)
はと同じでNumber(N)
、を返すだけN
です。その事実は後で使用します。
Array.apply(null, [undefined, undefined, undefined])
Array(undefined, undefined, undefined)
3要素の配列を生成し、undefined
各要素に割り当てると同等です。
それをどのようにN要素に一般化できますか?どのようにArray()
機能するかを考えてみましょう。これは次のようになります。
function Array() {
if ( arguments.length == 1 &&
'number' === typeof arguments[0] &&
arguments[0] >= 0 && arguments &&
arguments[0] < 1 << 32 ) {
return [ … ]; // array of length arguments[0], generated by native code
}
var a = [];
for (var i = 0; i < arguments.length; i++) {
a.push(arguments[i]);
}
return a;
}
ECMAScriptの5ので、Function.prototype.apply(thisArg, argsArray)
また、その2番目のパラメータとしてアヒル型付けされた配列のようなオブジェクトを受け付けます。を呼び出すとArray.apply(null, { length: N })
、実行されます
function Array() {
var a = [];
for (var i = 0; i < /* arguments.length = */ N; i++) {
a.push(/* arguments[i] = */ undefined);
}
return a;
}
これで、各要素がに設定されたN要素の配列ができましたundefined
。これを呼び出す.map(callback, thisArg)
と、各要素はの結果に設定されcallback.call(thisArg, element, index, array)
ます。したがって、[undefined, undefined, …, undefined].map(Number.call, Number)
各要素を(Number.call).call(Number, undefined, index, array)
にマップします。これはと同じです。これは、Number.call(undefined, index, array)
以前に観察したように、に評価されindex
ます。これで、要素がインデックスと同じである配列が完成しました。
なぜArray.apply(null, {length: N})
ただの代わりにのトラブルを経験するのArray(N)
ですか?結局のところ、両方の式は、未定義の要素のN要素の配列になります。違いは、前者の式では各要素が明示的に未定義に設定されているのに対し、後者では各要素が設定されたことはないということです。のドキュメントによると.map()
:
callback
値が割り当てられている配列のインデックスに対してのみ呼び出されます。削除されたインデックス、または値が割り当てられていないインデックスに対しては呼び出されません。
したがって、Array(N)
不十分です。Array(N).map(Number.call, Number)
結果は、長さがNの初期化されていない配列になります。
この手法はFunction.prototype.apply()
ECMAScript 5 で指定された動作に依存しているため、Chrome 14やInternet Explorer 9などのECMAScript 5より前のブラウザーでは機能しません。
Function.prototype.call
の最初のパラメーターがのイテレーターパラメーターにthis
直接マップするオブジェクトであるという事実を利用するとArray.prototype.map
、ある程度の輝きがあります。
map
私の意見では、割り当てられていない値の特異性です。別のバージョンが(そしておそらく少し明確に、長くはあるが)である: Array.apply(null, { length: N }).map(function(element, index) { return index; })
Array.apply(null, new Array(N)).map(function(_,i) { return i; })
または、es6および矢印関数の場合はさらに短い:Array.apply(null, new Array(N)).map((_,i) => i)
...
)とキーメソッドの使用[ ...Array(N).keys() ].map( i => i+1);
Array(N).fill().map((_, i) => i+1);
Array.from(Array(N), (_, i) => i+1)
{ length: N }
hackArray.from({ length: N }, (_, i) => i+1)
変化させることにより、かなり上の任意の所望の値に初期化缶生産アレイ上のすべての形態i+1
(例えば、必要な式にi*2
、-i
、1+i*2
、i%2
およびなど)。式が何らかの関数で表現できる場合f
、最初の形式は単純になります
[ ...Array(N).keys() ].map(f)
Array.from({length: 5}, (v, k) => k+1);
// [1,2,3,4,5]
配列はundefined
各位置で初期化v
されるため、の値はundefined
f
すなわち[ ...Array(N).keys() ].map((i) => f(i))
またはさらに簡単に
[ ...Array(N).keys() ].map(f)
k++
、を使用せず、を使用してください++k
。
配列は元々長さを管理します。それらがトラバースされると、それらのインデックスはメモリに保持され、その時点で参照されます。ランダムなインデックスを知る必要がある場合は、このindexOf
方法を使用できます。
これは、あなたのニーズのために、あなたは特定のサイズの配列を宣言したいかもしれないと言いました:
var foo = new Array(N); // where N is a positive integer
/* this will create an array of size, N, primarily for memory allocation,
but does not create any defined values
foo.length // size of Array
foo[ Math.floor(foo.length/2) ] = 'value' // places value in the middle of the array
*/
スプレッド演算子(...
)とkeys
メソッドを使用すると、サイズNの一時配列を作成してインデックスを作成し、次に変数に割り当てることができる新しい配列を作成できます。
var foo = [ ...Array(N).keys() ];
最初に必要な配列のサイズを作成し、それを未定義で埋め、次にを使用して新しい配列を作成map
します。これにより、各要素がインデックスに設定されます。
var foo = Array(N).fill().map((v,i)=>i);
これは、サイズNの長さに初期化し、1回のパスで配列を生成する必要があります。
Array.from({ length: N }, (v, i) => i)
コメントと混乱の代わりに、上記の例で1..Nから値を取得したい場合は、いくつかのオプションがあります。
++i
。 インデックスが使用されない場合、そしておそらくより効率的な方法は、配列を作成することですが、NをN + 1にしてから、前に移動します。
したがって、100個の数値が必要な場合:
let arr; (arr=[ ...Array(101).keys() ]).shift()
ES6でできること:
Array(N).fill().map((e,i)=>i+1);
http://jsbin.com/molabiluwa/edit?js,console
編集:質問を更新Array(45)
したArray(N)
ため、に変更されました。
console.log(
Array(45).fill(0).map((e,i)=>i+1)
);
.join.split
バージョン-しかし、私はまだ謙虚なループが優れていると思います。
map
はすぐにこのようなものの標準になると思います。
const gen = N => [...(function*(){let i=0;while(i<N)yield i++})()]
.fill()
必要なのかわかりません。私はノードのreplでテストするときだとわかりますが、それ以降Array(1)[0] === undefined
、Array(1).fill(undefined)
makeでfill()を呼び出すとどのような違いがありますか?
非常に人気のあるアンダースコア_.rangeメソッドを使用する
// _.range([start], stop, [step])
_.range(10); // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
_.range(1, 11); // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
_.range(0, 30, 5); // => [0, 5, 10, 15, 20, 25]
_.range(0, -10, -1); // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
_.range(0); // => []
function range(start, end) {
var foo = [];
for (var i = start; i <= end; i++) {
foo.push(i);
}
return foo;
}
その後、
var foo = range(1, 5);
JavaScriptでこれを行う組み込みの方法はありませんが、複数回行う必要がある場合に作成するのに完全に有効なユーティリティ関数です。
編集:私の意見では、以下はより良い範囲関数です。たぶん私はLINQに偏っているからかもしれませんが、それはより多くのケースでより便利だと思います。あなたのマイレージは異なる場合があります。
function range(start, count) {
if(arguments.length == 1) {
count = start;
start = 0;
}
var foo = [];
for (var i = 0; i < count; i++) {
foo.push(start + i);
}
return foo;
}
Array
代わりにのArray.prototype
メソッドにします。
Array.range(1, 5)
おそらくもっと適切でしょうが、を書くことについて何かクールなものがあり[].range(1, 5)
ます。
foo = [1, 2, 3]; bar = foo.range(0, 10);
。しかし、それはただ...混乱を招くだけです。bar = Array.range(0, 10)
より明確で明示的です。範囲はインスタンスとは関係がないため、インスタンスメソッドにする理由はありません。
この質問には多くの複雑な答えがありますが、簡単な1行です:
[...Array(255).keys()].map(x => x + 1)
また、上記の記述は短い(そしてきちんとした)ものですが、次の方が少し高速だと思います(最大長:
127、Int8、
255、Uint8、
32,767、Int16、
65,535、Uint16、
2,147,483,647、Int32、
4,294,967,295、Uint32。
(new Uint8Array(255)).map(($,i) => i + 1);
このソリューションも2つの配列を作成し、追加の変数宣言 "$"を使用するため、あまり理想的ではありません(このメソッドを使用してそれを回避する方法は不明です)。私は次の解決策がこれを行うための絶対最速の方法だと思います:
for(var i = 0, arr = new Uint8Array(255); i < arr.length; i++) arr[i] = i + 1;
このステートメントが作成された後はいつでも、現在のスコープで変数「arr」を簡単に使用できます。
それから簡単な関数を作りたい場合(いくつかの基本的な検証を伴う):
function range(min, max) {
min = min && min.constructor == Number ? min : 0;
!(max && max.constructor == Number && max > min) && // boolean statements can also be used with void return types, like a one-line if statement.
((max = min) & (min = 0)); //if there is a "max" argument specified, then first check if its a number and if its graeter than min: if so, stay the same; if not, then consider it as if there is no "max" in the first place, and "max" becomes "min" (and min becomes 0 by default)
for(var i = 0, arr = new (
max < 128 ? Int8Array :
max < 256 ? Uint8Array :
max < 32768 ? Int16Array :
max < 65536 ? Uint16Array :
max < 2147483648 ? Int32Array :
max < 4294967296 ? Uint32Array :
Array
)(max - min); i < arr.length; i++) arr[i] = i + min;
return arr;
}
//and you can loop through it easily using array methods if you want
range(1,11).forEach(x => console.log(x));
//or if you're used to pythons `for...in` you can do a similar thing with `for...of` if you want the individual values:
for(i of range(2020,2025)) console.log(i);
//or if you really want to use `for..in`, you can, but then you will only be accessing the keys:
for(k in range(25,30)) console.log(k);
console.log(
range(1,128).constructor.name,
range(200).constructor.name,
range(400,900).constructor.name,
range(33333).constructor.name,
range(823, 100000).constructor.name,
range(10,4) // when the "min" argument is greater than the "max", then it just considers it as if there is no "max", and the new max becomes "min", and "min" becomes 0, as if "max" was never even written
);
したがって、上記の関数を使用すると、上記の超低速の「単純なワンライナー」が超高速でさらに短くなります。
range(1,14000);
fill
メソッドを使用した最新のjavascript :Array(255).fill(0,0,255)
あなたはこれを使うことができます:
new Array(/*any number which you want*/)
.join().split(',')
.map(function(item, index){ return ++index;})
例えば
new Array(10)
.join().split(',')
.map(function(item, index){ return ++index;})
次の配列を作成します:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
new Array(10).join().split(',').map(function() {return ++arguments[1]});
ですか?
join
、1回、1回split
、実際にやりたいことのために)解析する必要があるのは、あまり良くありません-好意から外れているようです。何らかの理由で、しかし古き良き時代のループを単に使用する方がはるかに良いでしょう!
ES6これはトリックを行います:
[...Array(12).keys()]
結果を確認してください:
[...Array(12).keys()].map(number => console.log(number))
[...Array(N + 1).keys()].slice(1)
1..Nを生成します
[...Array(N + 1).keys()]
このコードは空の配列を返しますが、プロダクションモードでは、開発モードを使用しても機能します。
.keys()
答えはすでに与えられた数年前と500 + upvotesを持っています。あなたの答えはそれに何を追加しますか?
たまたまd3.jsを使用している場合私のようにアプリでを、D3はこれを行うヘルパー関数を提供します。
したがって、0から4までの配列を取得するには、次のように簡単です。
d3.range(5)
[0, 1, 2, 3, 4]
そして、あなたが要求していたように1から5までの配列を取得するには:
d3.range(1, 5+1)
[1, 2, 3, 4, 5]
詳細については、このチュートリアルをご覧ください。
ES2015 / ES6スプレッドオペレーターの使用
[...Array(10)].map((_, i) => i + 1)
console.log([...Array(10)].map((_, i) => i + 1))
i + 1
より意味があり++i
ます。
これはおそらく、数値の配列を生成する最も速い方法です
最短
var a=[],b=N;while(b--)a[b]=b+1;
列をなして
var arr=(function(a,b){while(a--)b[a]=a;return b})(10,[]);
//arr=[0,1,2,3,4,5,6,7,8,9]
1から始めたい場合
var arr=(function(a,b){while(a--)b[a]=a+1;return b})(10,[]);
//arr=[1,2,3,4,5,6,7,8,9,10]
機能が必要ですか?
function range(a,b,c){c=[];while(a--)c[a]=a+b;return c}; //length,start,placeholder
var arr=range(10,5);
//arr=[5,6,7,8,9,10,11,12,13,14]
どうして?
while
最速のループです
直接設定は push
[]
より速い new Array(10)
それは短いです...最初のコードを見てください。次に、ここにある他のすべての関数を確認します。
あなたが好きならなしでは生きられないため
for(var a=[],b=7;b>0;a[--b]=b+1); //a=[1,2,3,4,5,6,7]
または
for(var a=[],b=7;b--;a[b]=b+1); //a=[1,2,3,4,5,6,7]
console.time()
直感を取得することではなく、証明のために、あなたはjsperf.com必要性と、それはあなたが他の人からの結果(異なるハードウェアなど)、ブラウザの交差を示す
var a=[],b=N;while(b--){a[b]=a+1};
あなたがlodashを使用している場合は、使用することができ_.rangeを:
_.range([start=0], end, [step=1])
開始から終了までの数値(正および/または負)の配列を作成します。負の開始が終了またはステップなしで指定されている場合、-1のステップが使用されます。endが指定されていない場合は、startで始まり、0に設定されます。
例:
_.range(4);
// ➜ [0, 1, 2, 3]
_.range(-4);
// ➜ [0, -1, -2, -3]
_.range(1, 5);
// ➜ [1, 2, 3, 4]
_.range(0, 20, 5);
// ➜ [0, 5, 10, 15]
_.range(0, -4, -1);
// ➜ [0, -1, -2, -3]
_.range(1, 4, 0);
// ➜ [1, 1, 1]
_.range(0);
// ➜ []
充填の新しい方法Array
は次のとおりです。
const array = [...Array(5).keys()]
console.log(array)
結果は次のようになります: [0, 1, 2, 3, 4]
ES6でできること:
// `n` is the size you want to initialize your array
// `null` is what the array will be filled with (can be any other value)
Array(n).fill(null)
map
とforEach
動作します。
最終要約レポート.. Drrruummm Rolll-
これは、ES6を使用せずにサイズN(ここでは10)の配列を生成するための最短のコードです。上記のCoccoのバージョンは近いですが、最短ではありません。
(function(n){for(a=[];n--;a[n]=n+1);return a})(10)
しかし、このコードゴルフ(ソースコードの最小バイトで特定の問題を解決するための競争)の誰もが認める勝者は、Niko Ruotsalainenです。配列コンストラクターとES6スプレッド演算子を使用します。(ES6構文のほとんどは有効なtypeScriptですが、以下はそうではありません。そのため、使用する際は慎重に行ってください)
[...Array(10).keys()]
a
。ループはfor(var a=[];n--;a[n]=n+1)
ES6には、2つの引数を取るArray.fromを使用する別の方法があります。1つ目はarrayLike(この場合はlength
プロパティを持つオブジェクト)、2つ目はマッピング関数(この場合はアイテムをそのインデックスにマッピングします)です。
Array.from({length:10}, (v,i) => i)
これは短く、偶数を生成するような他のシーケンスに使用できます
Array.from({length:10}, (v,i) => i*2)
また、これは配列を1回だけループするため、他のほとんどの方法よりもパフォーマンスが優れています。比較のために抜粋を確認してください
// open the dev console to see results
count = 100000
console.time("from object")
for (let i = 0; i<count; i++) {
range = Array.from({length:10}, (v,i) => i )
}
console.timeEnd("from object")
console.time("from keys")
for (let i =0; i<count; i++) {
range = Array.from(Array(10).keys())
}
console.timeEnd("from keys")
console.time("apply")
for (let i = 0; i<count; i++) {
range = Array.apply(null, { length: 10 }).map(function(element, index) { return index; })
}
console.timeEnd("apply")
Array.from({length:N}, (v,i) => i+1)
=>
ES6標準の新しい配列メソッドと関数構文を使用する(執筆時点ではFirefoxのみ)。
穴を埋めることによりundefined
:
Array(N).fill().map((_, i) => i + 1);
Array.from
期待どおりに機能するundefined
ように「穴」を回しますArray.map
:
Array.from(Array(5)).map((_, i) => i + 1)
Array.from({length: N}, (v, k) => k)
。
Array.prototype.map.call
は、から返されるNodeLists など、のような冗長なアプローチに頼らずに、配列のようなものに対してArrayメソッドを使用したいという一般的な問題に対する優れたソリューションdocument.querySelectorAll
です。developer.mozilla.org/en/docs/Web/JavaScript/Reference/...
Array.from
は、スパース値を未定義に変換するのはそうではありません。むしろArray(5)
引数オブジェクトとして呼び出され、疎オブジェクトは未定義の値として解釈されます:)
Array(...Array(9)).map((_, i) => i);
console.log(Array(...Array(9)).map((_, i) => i))
[...Array(9)].map((_, i) => i)
ちょうど別のES6バージョン。
Array.from
2番目のオプションの引数を使用することにより:
Array.from(arrayLike [、mapFn [、thisArg]])
空のArray(10)
位置から番号付き配列を構築できます。
Array.from(Array(10), (_, i) => i)
var arr = Array.from(Array(10), (_, i) => i);
document.write(arr);
[...Array(11).keys()].slice(1)
ます。
現在、このかなり完全な回答リストにない唯一のフレーバーは、ジェネレーターを特徴とするものです。それを改善するには:
const gen = N => [...(function*(){let i=0;while(i<N)yield i++})()]
このように使用できます:
gen(4) // [0,1,2,3]
これの良い点は、インクリメントする必要がないことです... @ igor-shubinが与えた答えからインスピレーションを得るために、ランダムの配列を非常に簡単に作成できます。
const gen = N => [...(function*(){let i=0;
while(i++<N) yield Math.random()
})()]
そして、次のような長くて運用上高価なものではありません。
const slow = N => new Array(N).join().split(',').map((e,i)=>i*5)
// [0,5,10,15,...]
あなたは代わりに行うことができます:
const fast = N => [...(function*(){let i=0;while(i++<N)yield i*5})()]
Es6の配列塗りつぶしとマップを使用できます。ちょうどいくつかの人々がこの質問に対して与えた答えで提案したように。以下にいくつかの例を示します。
Example-One: Array(10).fill(0).map((e,i)=>i+1)
Result-One: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Example-Two: Array(100/10).fill(0).map((e,i)=>(i*10)+10)
Result-Two:[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
私はそれが簡単でわかりやすいので、これを好みます。
Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step));
ソース:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
ES6の使用
const generateArray = n => [...Array(n)].map((_, index) => index + 1);
Array.from(Array(n))
スプレッド演算子がサポートされていない場合にも使用できます。
Object.keys(Array.apply(0, Array(3))).map(Number)
を返します[0, 1, 2]
。イゴールシュビンの優れた答えに非常に似ていますに、トリックが少し少なくなっています(1文字長くなっています)。
Array(3) // [undefined × 3]
長さn = 3の配列を生成します。残念ながら、この配列はほとんど役に立たないので、…Array.apply(0,Array(3)) // [undefined, undefined, undefined]
配列を反復可能にします。注意:nullは、applyの最初の引数としてより一般的ですが、0の方が短いです。Object.keys(Array.apply(0,Array(3))) // ['0', '1', '2']
次に、配列のキーを取得します(配列はtypeof配列であるため機能します。配列はキーのインデックスを持つオブジェクトです。Object.keys(Array.apply(0,Array(3))).map(Number) // [0, 1, 2]
キーをマッピングし、文字列を数値に変換します。