Buat array dengan elemen yang sama diulang beberapa kali


323

Dalam Python, di mana [2]ada daftar, kode berikut memberikan hasil ini:

[2] * 5 # Outputs: [2,2,2,2,2]

Apakah ada cara mudah untuk melakukan ini dengan array di JavaScript?

Saya menulis fungsi berikut untuk melakukannya, tetapi apakah ada sesuatu yang lebih pendek atau lebih baik?

var repeatelem = function(elem, n){
    // returns an array with element elem repeated n times.
    var arr = [];

    for (var i = 0; i <= n; i++) {
        arr = arr.concat(elem);
    };

    return arr;
};


Jawaban:


52

Anda dapat melakukannya seperti ini:

function fillArray(value, len) {
  if (len == 0) return [];
  var a = [value];
  while (a.length * 2 <= len) a = a.concat(a);
  if (a.length < len) a = a.concat(a.slice(0, len - a.length));
  return a;
}

Ini menggandakan array di setiap iterasi, sehingga dapat membuat array yang sangat besar dengan beberapa iterasi.


Catatan: Anda juga dapat banyak meningkatkan fungsi dengan menggunakan pushalih-alih concat, karena concatakan membuat array baru setiap iterasi. Seperti ini (ditunjukkan hanya sebagai contoh bagaimana Anda dapat bekerja dengan array):

function fillArray(value, len) {
  var arr = [];
  for (var i = 0; i < len; i++) {
    arr.push(value);
  }
  return arr;
}

11
Ini jauh lebih efisien untuk mengalokasikan semua entri di muka, dengan arr = new Array(len);, lalu tetapkan kepada mereka dengan indeks dalam loop, yaitu arr[i] = value;. Dengan begitu Anda hanya membayar O (n) daripada harus terus merealokasi array saat itu tumbuh. Secara umum, selalu lebih baik untuk menghindari menumbuhkan array dengan menambahkan bila memungkinkan. Jika Anda tahu ukuran akhir, gunakan itu.
Tom Karzes

26
Array.from({length:5}).map(x => 2)
noobninja

1
@noobninja: solusi hebat; Anda harus memasukkannya kembali sebagai jawaban agar dapat dibatalkan.
jsalvata

693

Dalam ES6 menggunakan Array fill () metode

Array(5).fill(2)
//=> [2, 2, 2, 2, 2]

3
Internet Explorer dan Opera belum mendukungnya.
DenisKolodin

4
Node.js <= 3 tidak mendukung ini.
Junle Li

1
@DenisKolodin Opera Saat Ini tidak. Dan Edge juga. Lihat tabel-compat
Janus Troelsen

4
@Michael Anda bisa melakukannya dengan Array(5).fill([1,2,3]).flat(). Perhatikan bahwa flat () masih sangat eksperimental dan dukungan browser buruk.
Niko Ruotsalainen

3
Perhatikan bahwa argumen untuk filldievaluasi sekali, jadi Array(9).fill(someMutable)buat sembilan referensi ke someMutabledalam array (mutasi satu mutasi 'semuanya').
Carl Smith

146
>>> Array.apply(null, Array(10)).map(function(){return 5})
[5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
>>> //Or in ES6
>>> [...Array(10)].map((_, i) => 5)
[5, 5, 5, 5, 5, 5, 5, 5, 5, 5]

6
Pertanyaan konyol, tapi mengapa Array baru (10) .map tidak berfungsi?
blazkovicz

1
blazkovicz, lihat komentar zertosh tentang jawaban ini karena alasannya.
Ross Rogers

5
Dengan ES6, ini dapat "ditingkatkan" ke Array(...Array(10)).map(() => 5)dengan operator penyebaran atau juga keArray.from(Array(10)).map(() => 5)
Christophe Vidal

4
Menurut MDN , Anda bisa saja seperti ini:Array.from({length: 10}, () => 5);
Plusb Preco

2
@blazkovicz Array (10) membuat array lenght = 10tanpa properti enumerable. .maphanya bekerja pada properti enumerable. The .applymetode mengambil array ini, dan peta menjadi sebuah arguments array(sebuah objek array-seperti) yang akan diteruskan ke Arrayfungsi konstruktor. Array argumen tidak dapat jarang sehingga properti yang hilang diatur ke undefineddan menjadi enumerable. Sekarang kita dapat menggunakan .mapseperti yang dimaksudkan
CervEd

91

Anda dapat mencoba:

Array(6).join('a').split(''); // returns ['a','a','a','a','a'] (5 times)

Pembaruan (01/06/2018) :

Sekarang Anda dapat memiliki satu set karakter yang berulang.

new Array(5).fill('a'); // give the same result as above;
// or
Array.from({ length: 5 }).fill('a')

Catatan: Periksa lebih lanjut tentang isian (...) dan dari (...) untuk kompatibilitas dan dukungan browser.

Pembaruan (05/11/2019) :

Cara lain, tanpa menggunakan fillatau from, yang berfungsi untuk string dengan panjang berapa pun:

Array.apply(null, Array(3)).map(_ => 'abc') // ['abc', 'abc', 'abc']

Sama seperti jawaban di atas . Menambah demi kelengkapan.


1
Bagus. Terpendek dan sederhana.
Johann Echavarria

2
+1 untuk penanganan sederhana. Sayang sekali Anda tidak bisa membuat array string kosong dari itu. Terlepas dari itu sangat cerdas ...
Lebih cepat

1
Array (6) .join ('a'). Split ('a') memberi saya array string kosong.
Vivek

17
Ini hanya berfungsi untuk 1 string char, jadi itu tidak menjawab pertanyaan sepenuhnya.
az_

3
@ AlfonsoVergara: Dalam Javascript, String adalah tipe primitif (nilai-semantik); tidak ada cara untuk mendapatkan dua string untuk referensi data yang sama (karena string bukan referensi dalam Javascript; mereka nilai). Anda harus berhati-hati dengan referensi semantik dengan objek dan daftar, tetapi tidak dengan string.
Quuxplusone

36

Array.from({length:5}, i => 1) // [1, 1, 1, 1, 1]

atau buat array dengan nilai yang meningkat

Array.from({length:5}, (e, i)=>i) // [0, 1, 2, 3, 4]


Bagus, 👍 ini adalah pendekatan terbaik jika Anda memerlukan elemen untuk dinamis
IliasT

Array.from({length:5}, i => 1)=> iadalah undefinedkarena itu merupakan nilai kosong Array.from({length:5}, (e, i)=>i)=> eadalah undefinedkarena itu mewakili nilai kosong. Seharusnya Array.from({length:5}, v => 1)danArray.from({length:5}, (v, i)=>i)
Rafal Enden

33

Di lodash tidak begitu buruk:

_.flatten(_.times(5, function () { return [2]; }));
// [2, 2, 2, 2, 2]

EDIT : Lebih baik lagi:

_.times(5, _.constant(2));
// [2, 2, 2, 2, 2]

EDIT : Lebih baik lagi:

_.fill(Array(5), 2);

3
_.times (panjang, _.constant (nilai))
user1533401

1
dari docs: _.fill (Array (3), 2); Yang tidak jauh dari ES6
kert

15

[c] * n dapat ditulis sebagai:

Array(n+1).join(1).split('').map(function(){return c;})

sehingga untuk [2] * 5

Array(6).join(1).split('').map(function(){return 2;})

Sebenarnya, bukankah Array (6) .join (2) .sit ('') lebih mudah? Mengapa Anda membutuhkan peta?
Angela

4
yang mengembalikan ["2", "2", "2", "2", "2"], alih-alih [2, 2, 2, 2, 2].
sungai hong

10

Anda juga dapat memperluas fungsionalitas Array seperti:

Array.prototype.fill = function(val){
    for (var i = 0; i < this.length; i++){
        this[i] = val;
    }
    return this;
};
// used like:
var arry = new Array(5)​.fill(2);
// or
var arry = new Array(5);
arry.fill(2);


console.log(arry);​ //[2, 2, 2, 2, 2] 

Saya harus mencatat bahwa memperluas fungsionalitas objek bawaan dapat menyebabkan masalah jika Anda bekerja dengan perpustakaan pihak ketiga. Selalu timbang ke dalam keputusan Anda.


Perhatikan bahwa jika Anda melewatkan objek ke fillsetiap indeks dalam array akan merujuk ke objek yang sama, jadi mengubah satu akan mengubah semuanya. Ini tidak terlalu sulit untuk dipecahkan jika itu menjadi masalah.
Shmiddty

Saya tidak mengerti mengapa banyak pengguna javascript tidak mengetahui persyaratan untuk tidak membuat prototipe fungsi asli.
brooNo

2
Sebuah metode mengisi telah ditambahkan di ES6. Jadi saya tidak akan merekomendasikan menambahkan barang-barang Anda sendiri ke prototipe, Anda akan menimpa versi yang lebih cepat dan lebih mampu.
Janus Troelsen

1
@JanusTroelsen Untuk menghindari menimpa javascript atau perpustakaan pihak ketiga, Anda dapat memeriksa apakah ada sebelum menyatakannya. if (!Array.prototype.fill) { }
Oliver

1
@ JanusTroelsen Apa yang Anda maksud dengan "polyfill asli" ?. Saya menggunakan polifyll. Maksud saya: periksa untuk deteksi dan implementasi fitur jika tidak.
Oliver


5

Jika Anda perlu mengulangi array beberapa kali:

var arrayA = ['a','b','c'];
var repeats = 3;
var arrayB = Array.apply(null, {length: repeats * arrayA.length})
        .map(function(e,i){return arrayA[i % arrayA.length]});
// result: arrayB = ['a','b','c','a','b','c','a','b','c']

terinspirasi oleh jawaban ini


di es6, Anda dapat melakukan "abc" .ulangi (3)
Janus Troelsen

4

Tidak ada cara yang lebih mudah. Anda perlu membuat lingkaran dan mendorong elemen ke dalam array.


Terima kasih! Sebelum saya menerima, apakah pushlebih baik atau concatlebih baik, dalam hal efisiensi?
Curious2learn

CONCAT perlu memeriksa dua array, PUSH hanya menambahkan elemen lain, jadi saya berharap PUSH lebih efisien secara umum, tetapi untuk DATA IDENTIK, saya pikir jawaban Guffa berhasil.
Diodeus - James MacFarlane

Tidak perlu loop, lihat jawaban saya.
Janus Troelsen

@ JanusTroelsen, tidak perlu mengulang kecuali Anda ingin cara yang efisien untuk melakukan tindakan ini. Milik Anda adalah salah satu dari implementasi lambat yang dapat Anda temukan. push () ke [] adalah yang tercepat.
chrilith

4

Gunakan fungsi ini:

function repeatElement(element, count) {
    return Array(count).fill(element)
}
>>> repeatElement('#', 5).join('')
"#####"

Atau untuk versi yang lebih ringkas:

const repeatElement = (element, count) =>
    Array(count).fill(element)
>>> repeatElement('#', 5).join('')
"#####"

Atau untuk versi kari:

const repeatElement = element => count =>
    Array(count).fill(element)
>>> repeatElement('#')(5).join('')
"#####"

Anda dapat menggunakan fungsi ini dengan daftar:

const repeatElement = (element, count) =>
    Array(count).fill(element)

>>> ['a', 'b', ...repeatElement('c', 5)]
['a', 'b', 'c', 'c', 'c', 'c', 'c']

4

Jika Anda perlu mengulang array, gunakan yang berikut ini.

Array.from({ length: 3 }).fill(['a','b','c']).flat()

akan kembali

Array(9) [ "a", "b", "c", "a", "b", "c", "a", "b", "c" ]

oneliner hebat menggunakan array yang ada, apa yang saya butuhkan.
Gnerik

2

Satu kalimat lagi:

Array.prototype.map.call([]+Array(5+1),function(){ return '2'; })

1

Fungsi ini menciptakan array elemen (panjang) di mana setiap elemen sama dengan (nilai) selama (nilai) adalah bilangan bulat atau string bilangan bulat. Angka desimal apa pun akan terpotong. Jika Anda ingin angka desimal, ganti "parseInt ( " dengan " parseFloat ( "

function fillArray(length, intValue) {
     var vals = (new Array(length + 1)).join(intValue + '|').split('|').slice(0,length);
     for(var i = 0; i < length; i += 1) {
         vals[i] = parseInt(vals[i]);
     }
     return vals;
}

Contoh:

fillArray(5, 7) // returns [7,7,7,7,7]
fillArray(5, 7.5) // returns [7,7,7,7,7]
fillArray(5, 200) // returns [200,200,200,200,200]

1

Saya punya masalah dengan metode yang disebutkan ketika saya menggunakan array seperti

var array = ['foo', 'bar', 'foobar'];
var filled = array.fill(7);

//filled should be ['foo', 'bar', 'foobar', 'foo', 'bar', 'foobar', 'foo']

Untuk mendapatkan ini saya menggunakan:

Array.prototype.fill = function(val){
    var l = this.length;
    if(l < val){
        for(var i = val-1-l; i >= 0; i--){
            this[i+l] = this[i % l];
        }
    }
    return this;
};

Ini bagus, tetapi mungkin harus dinamai cycle.
Drenmi

1

Saya menemukan ini hari ini ketika mencoba membuat array 2D tanpa menggunakan loop. Dalam retrospeksi, bergabung dengan array baru rapi; Saya mencoba memetakan array baru, yang tidak berfungsi karena peta melompati slot kosong.

"#".repeat(5).split('').map(x => 0)

Karakter "#" dapat berupa karakter tunggal apa pun yang valid. Angka 5 akan menjadi variabel untuk jumlah elemen yang Anda inginkan. 7 akan menjadi nilai yang Anda ingin isi dengan array Anda.

Metode pengisian baru lebih baik, dan ketika saya mengkodekan ini saya tidak tahu itu ada, saya juga tidak tahu bahwa pengulangan adalah es6; Saya akan menulis posting blog tentang menggunakan trik ini bersama-sama dengan mengurangi untuk melakukan hal-hal keren.

http://jburger.us.to/2016/07/14/functionally-create-a-2d-array/




0

Jika Anda menggunakan sabuk utlity seperti lodash / garis bawah Anda dapat melakukannya seperti ini :)

let result = _.map(_.times(foo), function() {return bar})

0

Dapat digunakan sebagai one-liner juga:

function repeat(arr, len) {
    while (arr.length < len) arr = arr.concat(arr.slice(0, len-arr.length));
    return arr;
}

0

Meningkatkan pada jawaban Vivek , ini berfungsi untuk string dengan panjang berapa pun, untuk mengisi array dengan panjang n:Array(n+1).join('[string to be repeated][separator]').split('[separator]').slice(0, n)


-1

Saya membutuhkan cara untuk mengulang / mengulangi array (dengan n item) m kali.

Misalnya, mendistribusikan daftar (orang) ke satu minggu / bulan. Katakanlah saya punya 3 nama, dan saya ingin mereka mengulanginya dalam seminggu:

fillArray(["Adam", "Blair", "Curtis"], 7); // returns ["Adam", "Blair", "Curtis", "Adam", "Blair", "Curtis", "Adam"]

function fillArray(pattern, count) {
    let result = [];
    if (["number", "string"].includes(typeof pattern)) {
        result = new Array(5);
        result.fill(pattern);
    }
    else if (pattern instanceof Array) {
        for (let i = 0; i < count; i++) {
            result = result.concat(pattern);
        }
        result = result.slice(0, count);
    }
    return result;
}

fillArray("a", 5);        // ["a", "a", "a", "a", "a"]
fillArray(1, 5);          // [1, 1, 1, 1, 1]
fillArray(["a", "b"], 5); // ["a", "b", "a", "b", "a"]
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.