Konversi ES6 Iterable ke Array

100

Katakanlah Anda memiliki Iterable Javascript ES6 seperti array yang Anda tahu sebelumnya akan memiliki panjang yang terbatas, apa cara terbaik untuk mengubahnya menjadi Javascript Array?

Alasan untuk melakukannya adalah karena banyak library js seperti garis bawah dan lodash hanya mendukung Array, jadi jika Anda ingin menggunakan salah satu fungsinya pada Iterable, pertama-tama harus diubah menjadi Array.

Dalam python Anda bisa menggunakan fungsi list (). Apakah ada yang setara di ES6?

Michael Bylstra
sumber
26
Array.from(iterable), lihat draft ECMA-262 ed 6 .
RobG

Jawaban:

156

Anda dapat menggunakan Array.from atau operator penyebaran .

Contoh:

let x = new Set([ 1, 2, 3, 4 ]);

let y = Array.from(x);
console.log(y); // = [ 1, 2, 3, 4 ]

let z = [ ...x ];
console.log(z); // = [ 1, 2, 3, 4 ]

XåpplI'-I0llwlg'I -
sumber
2
Hampir sama berlaku untuk struktur let m = new Map()data ES6 : untuk mendapatkan hanya nilai-nilai Peta, gunakan Array.fromatau sebarkan operator m.values(), sama untuk m.keys(). Jika tidak, Anda akan mendapatkan sebuah array dari array: [[key, value], [key, value]].
Nik Sumeiko
17

Ringkasan:

  • Array.from() fungsi, dibutuhkan iterable seperti pada input dan mengembalikan array dari iterable.
  • Operator penyebaran: ...dalam kombinasi dengan literal array.

const map = new Map([[ 1, 'one' ],[ 2, 'two' ]]);

const newArr1  = [ ...map  ];  // create an Array literal and use the spread syntax on it
const newArr2 = Array.from( map );  // 

console.log(newArr1, newArr2); 

Peringatan saat menyalin array:

Ketahuilah fakta bahwa melalui metode di atas hanya salinan dangkal yang dibuat saat kita ingin menyalin larik. Sebuah contoh akan menjelaskan masalah potensial:

let arr = [1, 2, ['a', 'b']];

let newArr = [ ...arr ];

console.log(newArr);

arr[2][0] = 'change';

console.log(newArr);

Di sini, karena larik bersarang, referensi disalin dan tidak ada larik baru yang dibuat. Oleh karena itu, jika kita memutasi larik bersarang dari larik lama, perubahan ini akan tercermin dalam larik baru (karena merujuk ke larik yang sama, referensi telah disalin).

Solusi untuk peringatan:

Kami dapat menyelesaikan masalah memiliki salinan yang dangkal dengan membuat klon yang dalam dari larik menggunakan JSON.parse(JSON.stringify(array)). Sebagai contoh:

let arr = [1, 2, ['a', 'b']]

let newArr = Array.from(arr);

let deepCloneArr = JSON.parse(JSON.stringify(arr));

arr[2][0] = 'change';

console.log(newArr, deepCloneArr)

Willem van der Veen
sumber
12

Anda dapat menggunakan metode Array.from , yang ditambahkan di ES6, tetapi hanya mendukung array dan objek yang dapat diulang seperti Maps dan Set (juga tersedia dalam ES6). Untuk objek biasa, Anda bisa menggunakan metode toArray Underscore atau metode toArray lodash, karena kedua perpustakaan sebenarnya memiliki dukungan yang bagus untuk objek, bukan hanya array. Jika Anda sudah menggunakan garis bawah atau lodash, untungnya mereka dapat menangani masalah tersebut untuk Anda, sekaligus menambahkan berbagai konsep fungsional seperti peta dan pengurangan untuk objek Anda.

Colin Hartwig
sumber
3

Pendekatan berikut diuji untuk Maps:

const MyMap = new Map([
  ['a', 1],
  ['b', 2],
  ['c', 3]
]);

const MyArray = [...MyMap].map(item => {
  return {[item[0]]: item[1]}
});

console.info( MyArray ); //[{"a", 1}, {"b", 2}, {"c": 3}]
Roma
sumber
Bukan apa yang diminta - lihat Array. Dari cara
João Antunes
0
 <<Your_Array>> = [].concat.apply([], Array.from( <<Your_IterableIterator>> ));
Dionis Oros
sumber
-4

Anda juga bisa melakukan:

let arr = [];
for (let elem of gen(...)){
    arr.push(elem);
}

Atau "cara yang sulit" menggunakan fungsi generator ES5 + ( Fiddle berfungsi di Firefox saat ini):

var squares = function*(n){
    for (var i=0; i<n; i++){
        yield i*i;
    }
}

var arr = [];
var gen = squares(10);
var g;
while(true){
    g = gen.next();
    if (g.done){
        break;
    }
    arr.push(g.value);
}

Keduanya adalah pendekatan yang tidak direkomendasikan namun dan hanya merupakan bukti konsep.

CodeManX
sumber