Преобразование ES6 Iterable в массив


100

Скажем, у вас есть массив Javascript ES6 Iterable, который, как вы заранее знаете, будет иметь конечную длину, как лучше всего преобразовать его в массив Javascript?

Причина этого заключается в том, что многие библиотеки js, такие как подчеркивание и lodash, поддерживают только массивы, поэтому, если вы хотите использовать какую-либо из их функций в Iterable, ее сначала необходимо преобразовать в массив.

В Python вы можете просто использовать функцию list (). Есть ли аналог в ES6?


26
Array.from(iterable)см. проект ECMA-262 ed 6 .
RobG

Ответы:


156

Вы можете использовать Array.from или оператор распространения .

Пример:

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 ]


2
Практически то же самое применимо и к структуре let m = new Map()данных ES6 : чтобы получить только значения карты, используйте Array.fromили оператор распространения m.values(), то же самое для m.keys(). В противном случае, вы получите массив массивов: [[key, value], [key, value]].
Ник Сумейко

17

Резюме:

  • Array.from() функция, она принимает итерацию, как на входе, и возвращает массив итерации.
  • Оператор распространения: ...в сочетании с литералом массива.

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

Будьте осторожны при копировании массивов:

Помните о том, что с помощью этих методов, описанных выше, создается только неглубокая копия, когда мы хотим скопировать массив. Пример проясняет потенциальную проблему:

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

let newArr = [ ...arr ];

console.log(newArr);

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

console.log(newArr);

Здесь из-за вложенного массива ссылка копируется, а новый массив не создается. Поэтому, если мы изменим вложенный массив старого массива, это изменение будет отражено в новом массиве (поскольку они относятся к одному и тому же массиву, ссылка была скопирована).

Решение для предостережения:

Мы можем решить проблему с мелкими копиями, создав глубокий клон массива с помощью JSON.parse(JSON.stringify(array)). Например:

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)


12

Вы можете использовать метод Array.from , который добавляется в ES6, но поддерживает только массивы и повторяемые объекты, такие как Карты и Наборы (также входящие в ES6). Для обычных объектов вы можете использовать метод toArray в Underscore или метод toArray lodash, поскольку обе библиотеки на самом деле имеют отличную поддержку для объектов, а не только для массивов. Если вы уже используете подчеркивание или lodash, то, к счастью, они могут решить эту проблему за вас, наряду с добавлением различных функциональных концепций, таких как карта и сокращение для ваших объектов.


3

Для Карт протестирован следующий подход:

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

Не то, о чем спрашивали - см. Array.from way
Жуан Антунес,


-4

Вы также можете:

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

Или "сложный путь" с использованием функции генератора ES5 + ( Fiddle работает в текущем Firefox):

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

Однако оба этих подхода, безусловно, не рекомендуются и представляют собой просто доказательство концепции.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.