Cara membuat array yang berisi 1 ... N

1163

Saya mencari alternatif di bawah ini untuk membuat larik JavaScript yang berisi 1 hingga N di mana N hanya dikenal saat runtime.

var foo = [];

for (var i = 1; i <= N; i++) {
   foo.push(i);
}

Bagi saya rasanya harus ada cara untuk melakukan ini tanpa loop.

Bapak baptis
sumber
224
Setelah membaca seluruh halaman ini, saya sampai pada kesimpulan bahwa for-loop sederhana Anda sendiri adalah yang paling sederhana, paling mudah dibaca, dan paling tidak rentan kesalahan.
Kokodoko
Jika ada yang membutuhkan sesuatu yang lebih maju, saya membuat lib node.js yang melakukan ini untuk angka, huruf, rentang negatif / positif, dll . Github.com/jonschlinkert/fill-range . Ini digunakan di github.com/jonschlinkert/braces untuk ekspansi brace dan github.com/jonschlinkert/micromatch untuk pola glob
jonschlinkert
1
Anda harus mengedit untuk mengatakan "Cara membuat array dengan panjang N" bukan "... mengandung 1 ... N", yang terakhir menyiratkan akan ada elemen dengan nilai 1 hingga N
Steven Landow
7
@ SevenLandow mengapa OP harus mengganti nama? Dia ingin array dengan nilai 1 ... N?
Andre Elrico
Pertanyaan bagus, judul bagus, (agak) jawaban konyol.
Bitterblue

Jawaban:

381

Jika saya mendapatkan apa yang Anda cari, Anda menginginkan array angka 1..nyang nantinya bisa Anda lewati.

Jika ini yang Anda butuhkan, bisakah Anda melakukan ini?

var foo = new Array(45); // create an empty array with length 45

lalu ketika Anda ingin menggunakannya ... (tidak dioptimalkan, misalnya saja)

for(var i = 0; i < foo.length; i++){
  document.write('Item: ' + (i + 1) + ' of ' + foo.length + '<br/>'); 
}

mis. jika Anda tidak perlu menyimpan apa pun dalam array, Anda hanya perlu satu kontainer dengan panjang yang tepat yang bisa Anda ulangi ... ini mungkin lebih mudah.

Lihat beraksi di sini: http://jsfiddle.net/3kcvm/

scunliffe
sumber
4
terkesan Anda berhasil mengutarakan pertanyaan saya lebih baik daripada yang saya bisa, Anda memang benar karena pada refleksi semua yang saya butuhkan adalah array angka yang nantinya bisa saya lewati :) Terima kasih atas jawaban Anda.
Godders
147
@Pemuda: Jika ini yang Anda cari, mengapa Anda membutuhkan sebuah array? Sederhana var n = 45;dan kemudian perulangan dari 1..nakan dilakukan.
casablanca
3
@Godders - Untuk diketahui, jika Anda ingin mengurangi ukuran array setelah dibuat dengan panjang M, cukup gunakan foo.length = M--- Info cut off hilang. Lihat dalam aksi ==> jsfiddle.net/ACMXp
Peter Ajtai
24
Saya benar-benar tidak mengerti mengapa jawaban ini bahkan memiliki upvotes ... terutama ketika OP sendiri setuju itu tidak masuk akal dalam beberapa komentar di atas karena dia bisa saja melakukannya var n = 45;.
plalx
72
@scunliffe: Harap dicatat, itu new Array(45);tidak "membuat array elemen 45" (dalam arti yang sama seperti [undefined,undefined,..undefined]halnya). Ini agak "menciptakan array kosong dengan panjang = 45" ( [undefined x 45]), sama dengan var foo = []; foo.length=45;. Itu sebabnya forEach, dan maptidak akan berlaku dalam kasus ini.
tomalec
1310

Dalam ES6 menggunakan metode Array from () dan keys () .

Array.from(Array(10).keys())
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Versi lebih pendek menggunakan operator spread .

[...Array(10).keys()]
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Niko Ruotsalainen
sumber
75
Hanya sebuah catatan, ini akan selalu mulai dari 0. Akan perlu untuk rantai mapke array untuk menyesuaikan nilai ( [...Array(10).keys()].map(x => x++);) untuk mulai dari 1
Sterling Archer
32
Perubahan hanya map(x => x++)untuk map(x => ++x)karena kenaikan didahulukan terjadi setelah nilai kembali :)
Brock
93
Er apa !? Mengapa mapketika Anda bisa begitu saja slice? [...Array(N+1).keys()].slice(1)
Robin
19
Atau jangan gunakan keysdan hanya 1 peta ->Array.from(Array(10)).map((e,i)=>i+1)
yonatanmn
60
Atau jangan gunakan kunci dan peta dan hanya meneruskan fungsi pemetaan kefrom Array.from(Array(10), (e,i)=>i+1)
Fabio Antunes
844

Anda dapat melakukannya:

var N = 10; 
Array.apply(null, {length: N}).map(Number.call, Number)

hasil: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

atau dengan nilai acak:

Array.apply(null, {length: N}).map(Function.call, Math.random)

hasil: [0.7082694901619107, 0.9572225909214467, 0.8586748542729765, 0.8653848143294454, 0.008339877473190427, 0.9911756622605026, 0.8133423360995948, 0.837758846580948303530

Penjelasan

Pertama, perhatikan yang Number.call(undefined, N)setara dengan Number(N), yang baru saja kembali N. Kami akan menggunakan fakta itu nanti.

Array.apply(null, [undefined, undefined, undefined])setara dengan Array(undefined, undefined, undefined), yang menghasilkan array tiga elemen dan menetapkan undefineduntuk setiap elemen.

Bagaimana Anda bisa menggeneralisasikannya ke elemen N ? Pertimbangkan cara Array()kerjanya, yang kira-kira seperti ini:

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;
}

Sejak ECMAScript 5 , Function.prototype.apply(thisArg, argsArray)juga menerima objek seperti array bebek-mengetik sebagai parameter kedua. Jika kita memohon Array.apply(null, { length: N }), maka itu akan dieksekusi

function Array() {
    var a = [];
    for (var i = 0; i < /* arguments.length = */ N; i++) {
        a.push(/* arguments[i] = */ undefined);
    }
    return a;
}

Sekarang kita memiliki array N- elemen, dengan setiap elemen diatur ke undefined. Ketika kita memanggilnya .map(callback, thisArg), setiap elemen akan diatur ke hasil callback.call(thisArg, element, index, array). Oleh karena itu, [undefined, undefined, …, undefined].map(Number.call, Number)akan memetakan setiap elemen (Number.call).call(Number, undefined, index, array), yang sama dengan Number.call(undefined, index, array), yang, seperti yang kami amati sebelumnya, dievaluasi index. Itu melengkapi array yang elemennya sama dengan indeks mereka.

Mengapa harus melalui masalah Array.apply(null, {length: N})bukan hanya Array(N)? Setelah semua, kedua ekspresi akan menghasilkan array N -elemen elemen yang tidak terdefinisi. Perbedaannya adalah bahwa dalam ekspresi sebelumnya, setiap elemen secara eksplisit diatur ke tidak terdefinisi, sedangkan pada yang terakhir, setiap elemen tidak pernah ditetapkan. Menurut dokumentasi .map():

callbackdipanggil hanya untuk indeks array yang telah menetapkan nilai; itu tidak dipanggil untuk indeks yang telah dihapus atau yang tidak pernah diberi nilai.

Karena itu, Array(N)tidak cukup; Array(N).map(Number.call, Number)akan menghasilkan sebuah array diinisiasi panjang N .

Kesesuaian

Karena teknik ini bergantung pada perilaku yang Function.prototype.apply()ditentukan dalam ECMAScript 5, itu tidak akan berfungsi di browser pra-ECMAScript 5 seperti Chrome 14 dan Internet Explorer 9.

Igor Shubin
sumber
62
+1 untuk kepintaran tetapi harap dicatat bahwa ini adalah pesanan yang lebih besar PERLAHAN daripada primitif untuk loop: jsperf.com/array-magic-vs-for
warpech
7
Sangat pintar - mungkin juga begitu. Memanfaatkan fakta bahwa Function.prototype.callparam pertama adalah thisobjek untuk memetakan secara langsung Array.prototype.mapparameter iterator memiliki kecemerlangan tertentu.
Noah Freitas
14
Ini benar-benar pintar (berbatasan dengan penyalahgunaan JS). Wawasan yang sangat penting di sini adalah keistimewaan mappada nilai-nilai yang belum ditentukan , menurut pendapat saya. Versi lain (dan mungkin sedikit lebih jelas, meskipun lebih lama) adalah: Array.apply(null, { length: N }).map(function(element, index) { return index; })
Ben Reich
6
@BenReich Bahkan lebih baik (dalam hal tingkat penyalahgunaan JS): Array.apply(null, new Array(N)).map(function(_,i) { return i; }) atau, dalam hal fungsi es6 dan panah, lebih pendek: Array.apply(null, new Array(N)).map((_,i) => i)
oddy
1
JIKA ini mengembalikan sebuah array yang dimulai pada 1, itu sebenarnya akan menjawab pertanyaan OP
Sarsaparilla
483

Berbagai cara menggunakan ES6

Menggunakan ...metode spread operator ( ) dan kunci

[ ...Array(N).keys() ].map( i => i+1);

Isi / Peta

Array(N).fill().map((_, i) => i+1);

Dari Array

Array.from(Array(N), (_, i) => i+1)

Array.dari dan { length: N }retas

Array.from({ length: N }, (_, i) => i+1)

Perhatikan tentang formulir umum

Semua bentuk di atas array dapat menghasilkan dijalankan dengan nilai-nilai hampir semua yang diinginkan dengan mengubah i+1ekspresi diperlukan (misalnya i*2, -i, 1+i*2, i%2dan sebagainya). Jika ekspresi dapat diekspresikan oleh beberapa fungsi fmaka bentuk pertama menjadi sederhana

[ ...Array(N).keys() ].map(f)

Contoh:

Array.from({length: 5}, (v, k) => k+1); 
// [1,2,3,4,5]

Karena array diinisialisasi dengan undefinedpada setiap posisi, nilai v akanundefined

Contoh menampilkan semua formulir

Contoh yang lebih generik dengan fungsi initialiser kustom fyaitu

[ ...Array(N).keys() ].map((i) => f(i))

atau bahkan lebih sederhana

[ ...Array(N).keys() ].map(f)

Abdennour TOUMI
sumber
33
IMHO jawaban terbaik. Lihat juga developer.mozilla.org/de/docs/Web/JavaScript/Reference/…
le_m
5
Gunakan k ++ untuk array mulai dari 0
Borgboy
1
Jika Anda ingin menambah, jangan gunakan k++, gunakan ++k.
Alex
4
Waspadalah Array.from tidak didukung di IE, kecuali jika Anda mengisinya.
Lauren
2
Untuk membuat TS compiler senang, pertimbangkan mengganti param yang tidak digunakan dengan lodash: Array.from ({length: 5}, (_, k) => k + 1);
Journeycorner
297

Array secara alami mengatur panjangnya. Ketika mereka dilalui, indeks mereka dapat disimpan dalam memori dan direferensikan pada saat itu. Jika indeks acak perlu diketahui, indexOfmetode ini dapat digunakan.


Ini mengatakan, untuk kebutuhan Anda, Anda mungkin hanya ingin mendeklarasikan array dengan ukuran tertentu:

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
*/


ES6

Sebaran

Memanfaatkan operator spread ( ...) dan keysmetode, memungkinkan Anda untuk membuat array sementara ukuran N untuk menghasilkan indeks, dan kemudian array baru yang dapat ditugaskan ke variabel Anda:

var foo = [ ...Array(N).keys() ];

Isi / Peta

Pertama-tama Anda dapat membuat ukuran array yang Anda butuhkan, mengisinya dengan undefined dan kemudian membuat array baru menggunakan map, yang menetapkan setiap elemen ke indeks.

var foo = Array(N).fill().map((v,i)=>i);

Dari Array

Ini harus dimulai dengan panjang ukuran N dan mengisi array dalam satu lintasan.

Array.from({ length: N }, (v, i) => i)



Sebagai pengganti komentar dan kebingungan, jika Anda benar-benar ingin menangkap nilai dari 1..N dalam contoh di atas, ada beberapa opsi:

  1. jika indeks tersedia, Anda cukup menambahkannya dengan satu (mis., ++i).
  2. dalam kasus di mana indeks tidak digunakan - dan mungkin cara yang lebih efisien - adalah membuat array Anda tetapi membuat N mewakili N +1, kemudian bergeser dari depan.

    Jadi, jika Anda menginginkan 100 angka:

    let arr; (arr=[ ...Array(101).keys() ]).shift()




vol7ron
sumber
Saya percaya ini berguna ketika array angka sedang digunakan untuk data yang tidak dapat diproses pada sisi penerima. (Seperti templat HTML yang hanya menggantikan nilai.)
Neil Monroe
Mengapa seseorang melakukan ini adalah memiliki array angka untuk mengisi daftar dropdown, memberikan pengguna pilihan dari 1 hingga 10. Sebuah array kecil dengan tangan [1,2,3 ... 10] masuk akal, tetapi bagaimana jika dari 1 hingga 50? Bagaimana jika nomor akhir berubah?
CigarDoug
@ CigarDoug Saya tidak ragu ada usecase, tapi saya kira kecil. Mengapa sebuah array angka diperlukan, biasanya ketika iterasi pada array, sebuah indeks akan digunakan sebagai bagian dari konstruksi loop - baik sebagai argumen untuk fungsi looping body, atau variabel counter - sehingga memegang array angka tampaknya sepele untuk hanya membuat array dengan lebar yang ditentukan, atau hanya variabel yang memegang batas atas array. Saya dapat memikirkan beberapa kasus penggunaan, tetapi tidak ada yang diungkapkan oleh OP
vol7ron
4
Seperti yang saya katakan, saya perlu mengisi dropdown dengan angka 1 hingga 10. Itu saja. ADA usecase, MY usecase. Begitulah cara saya menemukan halaman ini. Jadi hanya membangun array dengan tangan tidak lebih rumit dari apa yang saya lihat di sini. Jadi persyaratan saya bukanlah persyaratan OP. Tapi saya punya jawaban.
CigarDoug
1
@ vol7ron Ada usecase, saya juga punya satu. Dalam sudut, dalam paging, saya ingin menampilkan halaman di footer yang dapat diklik. Jadi saya mengulang elemen dalam tampilan dengan * ngFor = "let p of pagesCounter". Anda punya solusi yang lebih baik untuk itu? BTW, lihat stackoverflow.com/questions/36354325/…
Dalibor
186

Di ES6 Anda dapat melakukan:

Array(N).fill().map((e,i)=>i+1);

http://jsbin.com/molabiluwa/edit?js,console

Sunting: Diubah Array(45)ke Array(N)sejak Anda memperbarui pertanyaan.

console.log(
  Array(45).fill(0).map((e,i)=>i+1)
);

Nate
sumber
3
Memberi +1 karena keseluruhannya O besar lebih baik daripada .join.splitversi jahat - tapi saya masih berpikir bahwa loop sederhana lebih baik.
Robin
Saya setuju @Robin - Di samping kompleksitas Algoritma, loop sederhana selalu lebih mudah dibaca. Namun, dengan munculnya lambdas di Jawa, saya pikir mapakan segera menjadi standar untuk hal-hal seperti ini.
Nate
4
const gen = N => [...(function*(){let i=0;while(i<N)yield i++})()]
Robin
8
Saya tidak mengerti mengapa .fill()itu perlu. Saya melihat bahwa itu adalah ketika saya menguji pada node's repl, tetapi karena Array(1)[0] === undefined, apa bedanya panggilan untuk mengisi () pada Array(1).fill(undefined)make?
Dominic
11
Bagi siapa pun yang tertarik, perbedaan antara Array (N) dan Array (N) .fill () dijelaskan dengan baik di sini
Dominic
108

Gunakan metode _.range Garis Bawah yang sangat populer

// _.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); // => []
Evan
sumber
Luar biasa. Tunjukkan pada saya sebuah proyek besar yang tidak menggunakan garis bawah ...
Erez Cohen
63
function range(start, end) {
    var foo = [];
    for (var i = start; i <= end; i++) {
        foo.push(i);
    }
    return foo;
}

Kemudian dipanggil oleh

var foo = range(1, 5);

Tidak ada cara bawaan untuk melakukan ini dalam Javascript, tetapi ini adalah fungsi utilitas yang benar-benar valid untuk dibuat jika Anda perlu melakukannya lebih dari sekali.

Sunting: Menurut saya, berikut ini adalah fungsi rentang yang lebih baik. Mungkin hanya karena saya bias oleh LINQ, tapi saya pikir ini lebih berguna dalam banyak kasus. Jarak tempuh Anda mungkin beragam.

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;
}
Ian Henry
sumber
2
Saya suka ini. Jika Anda ingin bekerja lebih keras dengannya, Anda dapat mendeklarasikannya sebagai Array.prototype.range = function (start, end) {...} ;. Kemudian, Anda dapat memanggil rentang (x, y) pada objek Array apa pun.
Zach Rattner
8
Alih-alih menjadikannya metode Arrayalih - alih Array.prototypekarena tidak ada alasan (bahkan mungkin dianggap agak bodoh) untuk memiliki metode ini pada setiap array.
adamse
9
Array.range(1, 5)mungkin akan lebih tepat, tetapi ada sesuatu yang keren tentang penulisan [].range(1, 5).
MooGoo
"Alih-alih menjadikannya metode Array, bukan Array.prototype" - Apa bedanya? Maksud Anda hanya pada array tertentu?
pilau
3
@ Pilau Seperti kata Adam, itu terlihat aneh. Jika ada di prototipe, bisa Anda katakan foo = [1, 2, 3]; bar = foo.range(0, 10);. Tapi itu hanya ... membingungkan. bar = Array.range(0, 10)jauh lebih jelas dan eksplisit. Rentang tidak ada hubungannya dengan instance, jadi tidak ada alasan untuk menjadikannya metode instance.
Ian Henry
53

cara tercepat untuk mengisi Arrayv8 adalah:

[...Array(5)].map((_,i) => i);

hasilnya adalah: [0, 1, 2, 3, 4]

aflex dykyі
sumber
apakah ada cara untuk melakukannya tanpa variabel tambahan _
bluejayke
@bluejayke no :(
аlex dykyі
harsh, tahukah Anda apa kode sumber .map itu? Saya tidak yakin apakah ini lebih cepat daripada untuk loop, tetapi jika tidak maka secara teoritis kita bisa mendefinisikanProperty dan membuat yang baru
bluejayke
49

Pertanyaan ini memiliki banyak jawaban yang rumit, tetapi satu kalimat:

[...Array(255).keys()].map(x => x + 1)

Juga, meskipun di atas pendek (dan rapi) untuk menulis, saya pikir yang berikut ini sedikit lebih cepat (untuk panjang maksimal:

127, Int8,

255, Uint8,

32.767, Int16,

65.535, Uint16,

2,147.483.647, Int32,

4.294.967.295, Uint32.

(berdasarkan nilai integer maks ), juga berikut ini di Typed Arays ):

(new Uint8Array(255)).map(($,i) => i + 1);

Meskipun solusi ini juga tidak begitu ideal, karena ia menciptakan dua array, dan menggunakan deklarasi variabel tambahan "$" (tidak yakin ada cara untuk menyiasatinya menggunakan metode ini). Saya pikir solusi berikut adalah cara tercepat yang paling mungkin untuk melakukan ini:

for(var i = 0, arr = new Uint8Array(255); i < arr.length; i++) arr[i] = i + 1;

Kapan saja setelah pernyataan ini dibuat, Anda dapat menggunakan variabel "arr" sederhana di lingkup saat ini;

Jika Anda ingin membuat fungsi sederhana darinya (dengan beberapa verifikasi dasar):

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
);


jadi, dengan fungsi di atas, "satu-liner sederhana" super-lambat di atas menjadi super cepat, bahkan lebih pendek:

range(1,14000);
bluejayke
sumber
@ JPV tetapi tidak untuk fungsi yang lebih cepat?
bluejayke
Tepat sekali. Ini adalah liner sederhana yang dicari semua orang!
supersan
@supersan meskipun sangat lambat :)
bluejayke
Javascript modern dengan fillmetode baru :Array(255).fill(0,0,255)
cacoder
@cacoder seberapa cepat, berapa banyak array yang dibuatnya dan berapa banyak iterasinya?
bluejayke
42

Anda bisa menggunakan ini:

new Array(/*any number which you want*/)
    .join().split(',')
    .map(function(item, index){ return ++index;})

sebagai contoh

new Array(10)
    .join().split(',')
    .map(function(item, index){ return ++index;})

akan membuat array berikut:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
nktssh
sumber
Kenapa tidak new Array(10).join().split(',').map(function() {return ++arguments[1]});?
super
1
@Murplyx untuk beberapa kasus berfungsi dengan argumen di dalamnya tidak akan dioptimalkan oleh mesin JS (benar bahkan untuk V8, lihat jsperf.com/arguments-vs-array-argument/2 )
nktssh
4
Ini adalah solusi yang menarik tetapi sama sekali tidak praktis - harus mengurai array 3 kali (sekali ke join, sekali ke split, dan sekali untuk hal yang sebenarnya ingin Anda lakukan) tidak baik - Saya tahu mereka tampaknya tidak disukai untuk beberapa alasan, tetapi akan jauh lebih baik menggunakan loop kuno yang bagus !
Robin
42

ES6 ini akan melakukan trik:

[...Array(12).keys()]

lihat hasilnya:

[...Array(12).keys()].map(number => console.log(number))

Kristen
sumber
5
sebenarnya, mereka meminta 1..N, bukan 0..N-1
YakovL
1
ya, [...Array(N + 1).keys()].slice(1)akan menghasilkan 1..N
David G
Untuk beberapa alasan solusi ini tidak dapat berfungsi di Versi Produksi dari Aplikasi Expo (asli-reaksi). [...Array(N + 1).keys()]kode ini mengembalikan array kosong, tetapi hanya dalam mode produksi, menggunakan mode pengembangan berfungsi.
FabianoLothor
3
The .keys()jawaban sudah diberikan tahun yang lalu dan memiliki 500 + upvotes. Apa yang ditambahkan oleh jawaban Anda?
Dan Dascalescu
39

Jika Anda menggunakan d3.js di aplikasi Anda seperti saya, D3 menyediakan fungsi pembantu yang melakukan ini untuk Anda.

Jadi untuk mendapatkan array dari 0 hingga 4, semudah:

d3.range(5)
[0, 1, 2, 3, 4]

dan untuk mendapatkan array dari 1 hingga 5, saat Anda meminta:

d3.range(1, 5+1)
[1, 2, 3, 4, 5]

Lihatlah tutorial ini untuk informasi lebih lanjut.

Tyler Rick
sumber
Komentar ini memberi saya ide untuk mencari fungsi range () di RamdaJS, yang kebetulan merupakan pustaka JS yang sedang saya kerjakan pada proyek saya saat ini. Sempurna.
morphatic
39

Menggunakan operator penyebaran ES2015 / ES6

[...Array(10)].map((_, i) => i + 1)

console.log([...Array(10)].map((_, i) => i + 1))

Vlad Bezden
sumber
7
i + 1akan lebih masuk akal daripada ++i.
Vincent Cantin
38

Ini mungkin cara tercepat untuk menghasilkan array angka

Terpendek

var a=[],b=N;while(b--)a[b]=b+1;

Di barisan

var arr=(function(a,b){while(a--)b[a]=a;return b})(10,[]);
//arr=[0,1,2,3,4,5,6,7,8,9]

Jika Anda ingin memulai dari 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]

Ingin fungsi?

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]

MENGAPA?

  1. while adalah loop tercepat

  2. Pengaturan langsung lebih cepat daripada push

  3. [] lebih cepat dari new Array(10)

  4. ini singkat ... lihat kode pertama. kemudian lihat semua fungsi lain di sini.

Jika Anda suka tidak bisa hidup tanpa untuk

for(var a=[],b=7;b>0;a[--b]=b+1); //a=[1,2,3,4,5,6,7]

atau

for(var a=[],b=7;b--;a[b]=b+1); //a=[1,2,3,4,5,6,7]
cocco
sumber
8
Akan lebih baik untuk mendukung klaim ini dengan tolok ukur. Coba jsperf.com .
Matt Ball
2
lol jsperf ... tolong Matt karena Anda tidak suka jawaban saya berhenti downvoting yang lain ... stackoverflow.com/a/18344296/2450730 ... gunakan console.time () atau bagaimana namanya ... TIDAK jsperf .
cocco
4
FYI: Seperti John Reisig pertama kali diterbitkan beberapa tahun yang lalu - pada beberapa platform (artinya windows: P), waktu diberikan ke browser sekali setiap 16ms. Juga ada masalah lain dengan mengukur waktu eksekusi di lingkungan multitasking. jsperf.com telah mengimplementasikan menjalankan tes sehingga secara statistik benar. Tidak masalah menjalankan console.time()untuk mendapatkan intuisi, tetapi sebagai buktinya, Anda memerlukan jsperf.com DAN itu menunjukkan kepada Anda hasil cross-browser dari orang lain (perangkat keras yang berbeda, dll)
naugtur
3
@cocco ini salah:var a=[],b=N;while(b--){a[b]=a+1};
vintagexav
5
@ cocco— sementara tidak selalu lebih cepat dari loop lain. Di beberapa peramban, perulangan sementara pengulangan jauh lebih lambat daripada perulangan untuk, Anda tidak dapat membuat pernyataan umum tentang kinerja javascript seperti itu karena ada begitu banyak implementasi dengan begitu banyak optimisasi berbeda. Namun, secara umum saya menyukai pendekatan Anda. ;-)
RobG
32

Jika Anda menggunakan lodash, Anda dapat menggunakan _.range :

_.range([start=0], end, [step=1])

Membuat susunan angka (positif dan / atau negatif) mulai dari awal hingga, tetapi tidak termasuk, akhir. Langkah -1 digunakan jika awal negatif ditentukan tanpa akhir atau langkah. Jika akhir tidak ditentukan, itu diatur untuk mulai dengan awal kemudian atur ke 0.

Contoh:

_.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);
// ➜ []
Hongbo Miao
sumber
32

cara baru untuk mengisi Arrayadalah:

const array = [...Array(5).keys()]
console.log(array)

hasilnya adalah: [0, 1, 2, 3, 4]

aflex dykyі
sumber
Ini jawaban yang sangat bagus, walaupun secara teknis pertanyaannya adalah dari 1-N, bukan 0 (N-1)
bluejayke
30

dengan ES6 yang dapat Anda lakukan:

// `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)

sumber
Karena nilai array sebenarnya diisi menggunakan solusi ini, mapdan forEachakan berfungsi.
dontmentionthebackup
27

Laporan Ringkasan Akhir .. Drrruummm Rolll -

Ini adalah kode terpendek untuk menghasilkan Array ukuran N (di sini 10) tanpa menggunakan ES6 . Versi Cocco di atas sudah dekat tapi bukan yang terpendek.

(function(n){for(a=[];n--;a[n]=n+1);return a})(10)

Tetapi pemenang yang tidak perlu dari golf Kode ini (persaingan untuk memecahkan masalah tertentu dalam byte kode sumber paling sedikit) adalah Niko Ruotsalainen . Menggunakan Array Constructor dan operator penyebaran ES6 . (Sebagian besar sintaks ES6 adalah jenis huruf yang valid, tetapi mengikuti tidak. Jadi berhati-hatilah saat menggunakannya)

[...Array(10).keys()]
lemah
sumber
Mengapa memilih? Daftar jawaban panjang sulit untuk diikuti, jadi pikirkan untuk meringkas.
Sapy
bukankah ini 0-10? [... Array (10) .key ()]
Greg
Webstorm menyarankan (new Array (10)). Keys (), benarkah?
Guy
(Array baru (10)) kunci (), mengembalikan ArrayIterator {}, tidak array.
sapy
Ini menciptakan variabel global a. Lingkaran harusfor(var a=[];n--;a[n]=n+1)
kube
20

Ada cara lain dalam ES6, menggunakan Array.from yang mengambil 2 argumen, yang pertama adalah arrayLike (dalam hal ini objek dengan lengthproperti), dan yang kedua adalah fungsi pemetaan (dalam hal ini kami memetakan item ke indeksnya)

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

ini lebih pendek dan dapat digunakan untuk urutan lain seperti menghasilkan bilangan genap

Array.from({length:10}, (v,i) => i*2)

Juga ini memiliki kinerja yang lebih baik daripada kebanyakan cara lain karena hanya loop sekali melalui array. Periksa snippit untuk beberapa perbandingan

// 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")

Gafi
sumber
Hei itu rapi, saya suka itu. Namun itu tidak mengembalikan hasil yang diharapkan OP. Untuk melakukan itu perlu ditulis sebagaiArray.from({length:N}, (v,i) => i+1)
CervEd
Retas neato ini masih lebih lambat 5-10x daripada yang lama untuk loop .
Dan Dascalescu
16

Menggunakan metode Array baru dan =>sintaks fungsi dari standar ES6 (hanya Firefox pada saat penulisan).

Dengan mengisi lubang dengan undefined:

Array(N).fill().map((_, i) => i + 1);

Array.frommengubah "lubang" menjadi undefinedbegitu Array.mapberfungsi seperti yang diharapkan:

Array.from(Array(5)).map((_, i) => i + 1)
szymzet
sumber
7
Demikian pula, Anda juga dapat melakukan berikut di ES6: Array.from({length: N}, (v, k) => k).
XåpplI'-I0llwlg'I -
Pendekatan Xappli lebih disukai: Array.from telah dibuat untuk hampir skenario yang tepat ini, dan itu menyiratkan pemetaan kembali callback. Ini adalah solusi yang sangat baik untuk masalah umum ingin menggunakan metode Array pada sesuatu seperti array, tanpa menggunakan pendekatan verbose seperti Array.prototype.map.call, misalnya untuk NodeLists kembali dari document.querySelectorAll. developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
Josh dari Qaribou
Saya menimbang ini vs sintaks kisaran garis bawah, dan rentang membaca lebih baik.
ooolala
Secara teknis bukan Array.fromyang mengubah nilai jarang menjadi tidak terdefinisi. Melainkan Array(5)disebut sebagai objek argumen yang pada gilirannya menginterpretasikan nilai jarang sebagai nilai yang tidak ditentukan :)
CervEd
15

Array(...Array(9)).map((_, i) => i);

console.log(Array(...Array(9)).map((_, i) => i))

aflex dykyі
sumber
Bagus! Bisa juga menulis ini sedikit lebih ringkas sebagai[...Array(9)].map((_, i) => i)
Eamonn O'Brien-Strain
13
for(var i,a=[i=0];i<10;a[i++]=i);

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

SammieFox
sumber
Sangat mengagumkan! Tx!
Pedro Ferreira
12

Dalam ES6:

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

ES5:

Array.apply(0, {length: 1000}).map(function(x,i){return i});
bluejayke
sumber
10

Hanya versi ES6 lainnya .

Dengan memanfaatkan Array.fromargumen opsional kedua:

Array.from (arrayLike [, mapFn [, thisArg]])

Kita dapat membangun array bernomor dari Array(10)posisi kosong :

Array.from(Array(10), (_, i) => i)

var arr = Array.from(Array(10), (_, i) => i);
document.write(arr);

zurfyx
sumber
Ini lebih rumit dan ~ 10x lebih lambat dari [...Array(11).keys()].slice(1).
Dan Dascalescu
10

Tampaknya satu-satunya rasa yang saat ini tidak ada dalam daftar jawaban yang agak lengkap ini adalah yang menampilkan generator; jadi untuk memperbaiki itu:

const gen = N => [...(function*(){let i=0;while(i<N)yield i++})()]

yang dapat digunakan demikian:

gen(4) // [0,1,2,3]

Hal yang menyenangkan tentang ini adalah Anda tidak hanya perlu menambah ... Untuk mengambil inspirasi dari jawaban yang diberikan @ igor-shubin, Anda dapat membuat susunan tebusan dengan sangat mudah:

const gen = N => [...(function*(){let i=0;
  while(i++<N) yield Math.random()
})()]

Dan bukan sesuatu yang panjang operasional mahal seperti:

const slow = N => new Array(N).join().split(',').map((e,i)=>i*5)
// [0,5,10,15,...]

Anda bisa melakukannya:

const fast = N => [...(function*(){let i=0;while(i++<N)yield i*5})()]
Robin
sumber
10

Anda dapat menggunakan isi Array dan memetakan dari Es6; seperti beberapa orang yang menyarankan jawaban yang mereka berikan untuk pertanyaan ini. Berikut adalah beberapa contoh:

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]

Saya lebih suka ini karena saya merasa lurus dan mudah.

Gbemi Kadri
sumber
9

Menggunakan ES6

const generateArray = n => [...Array(n)].map((_, index) => index + 1);
Geoffrey Abdallah
sumber
Terima kasih! Ini adalah jawaban paling elegan menurut saya! Satu juga dapat digunakan Array.from(Array(n))jika operator spread tidak didukung.
Amit
Pada awalnya saya tidak tahu mengapa Anda harus menggunakan operator spread, tetapi kemudian saya membaca tentang mapMDN berikut : "Tidak dipanggil untuk elemen array yang hilang (yaitu, indeks yang belum pernah ditetapkan, yang memiliki telah dihapus atau yang belum pernah diberi nilai). "
battmanz
9

Object.keys(Array.apply(0, Array(3))).map(Number)

Pengembalian [0, 1, 2]. Sangat mirip dengan jawaban sempurna Igor Shubin , tetapi dengan sedikit tipu daya (dan satu karakter lebih lama).

Penjelasan:

  • Array(3) // [undefined × 3]Hasilkan array dengan panjang n = 3. Sayangnya array ini hampir tidak berguna bagi kita, jadi kita harus ...
  • Array.apply(0,Array(3)) // [undefined, undefined, undefined]membuat array iterable. Catatan: null lebih umum sebagai arg pertama yang berlaku tetapi 0 lebih pendek.
  • Object.keys(Array.apply(0,Array(3))) // ['0', '1', '2'] kemudian dapatkan kunci-kunci array (berfungsi karena Array adalah tipe array adalah objek dengan indeks untuk kunci.
  • Object.keys(Array.apply(0,Array(3))).map(Number) // [0, 1, 2] dan memetakan di atas tombol, mengubah string menjadi angka.
mLuby
sumber