Повторите массив с несколькими элементами несколько раз в JavaScript - PullRequest
0 голосов
/ 04 июня 2018

В JavaScript, как я могу кратко повторить массив, который содержит несколько элементов?

В Ruby вы можете сделать:

irb(main):001:0> ["a", "b", "c"] * 3
=> ["a", "b", "c", "a", "b", "c", "a", "b", "c"]

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

const arrayToRepeat = [1, 2, 3];
const numberOfRepeats = 3;
const repeatedArray = _.flatten(_.times(numberOfRepeats, _.constant(arrayToRepeat)));

Вопросы Самый эффективный способ создания нулязаполненный массив JavaScript? и Создать массив с одним и тем же элементом, повторяющимся несколько раз , сосредоточиться на повторении только одного элемента несколько раз, тогда как я хочу повторить массив, который имеет несколько элементов.

Использование разумно ухоженных библиотек допустимо.

Ответы [ 7 ]

0 голосов
/ 04 июня 2018

Помимо очевидного решения [].concat + Array.from({length: 3}, …) / fill(), использование генераторов приведет к элегантному коду:

function* concat(iterable) {
    for (const x of iterable)
        for (const y of x)
            yield y;
}
function* repeat(n, x) {
    while (n-- > 0)
        yield x;
}

const repeatedArray = Array.from(concat(repeat(3, [1, 2, 3])));

Вы также можете сократить его до

function* concatRepeat(n, x) {
    while (n-- > 0)
        yield* x;
}

const repeatedArray = Array.from(concatRepeat(3, [1, 2, 3]));
0 голосов
/ 02 июля 2018

Хотя другие методы работают просто, они тоже.

Array.fill() и Array.from() в предыдущих методах не будут работать в IE. Документы MDN для справки

Mehtod 1 : зацикливание и вставка ( Array.prototype.push ) в массив.

function mutateArray(arr,n)
{
    var temp = [];
    while(n--) Array.prototype.push.apply(temp,arr);
    return temp;
}
var a = [1,2,3,4,5];
console.log(mutateArray(a,3));

Метод 2 : объединить элементы массива и String.repeat () , чтобы преобразовать строку и вернуть разделенную строку.

Примечание : метод repeat пока не поддерживается в IE и Android webviews.

function mutateArray(arr,n)
{
    var arr = (arr.join("$")+"$").repeat(n).split("$");
    arr.pop(); //To remove the last empty element
    return arr;
}
var a = [1,2,3,4,5];
console.log(mutateArray(a,3));
0 голосов
/ 04 июня 2018

Рекурсивная альтернатива:

const repeat = (a, n) => n-- ? a.concat(repeat(a, n)) : [];

console.log( repeat([1, 2], 3) )
0 голосов
/ 04 июня 2018

Вы можете использовать конструктор Array вместе с его методом fill, чтобы заполнить его несколько раз массивом, который вы хотите повторить, затем concat их (подмассивы) в один массив:

const repeatedArray = [].concat(...Array(num).fill(arr));

Примечание: В более старых браузерах (до ES6) вы можете использовать Function#apply для имитации приведенного выше синтаксиса остатка (concat будет вызываться с каждым из вложенных массивов, передаваемых вэто как аргумент):

var repeatedArray = [].concat.apply([], Array(num).fill(arr));

Пример:

const arrayToRepeat = [1, 2, 3];
const numberOfRepeats = 3;

const repeatedArray = [].concat(...Array(numberOfRepeats).fill(arrayToRepeat));

console.log(repeatedArray);
0 голосов
/ 04 июня 2018

К сожалению, это невозможно в JS (также невозможна перегрузка операторов, поэтому мы не можем использовать что-то вроде Array.prototype.__mul__), но мы можем создать массив с нужной целевой длиной, заполнить заполнителями, а затем повторноотобразить значения:

const seqFill = (filler, multiplier) => 
  Array(filler.length * multiplier)
  .fill(1)
  .map(
    (_, i) => filler[i % filler.length]
  );

console.log(seqFill([1,2,3], 3));
console.log(seqFill(['a','b','c', 'd'], 5));

Или, подключившись к прототипу Array, вы можете использовать синтаксис Array#seqFill(multiplier), это, вероятно, самый близкий к синтаксису ruby ​​(может сделать rb).в основном все с перегрузкой операторов, но JS не может):

Object.defineProperty(Array.prototype, 'seqFill', {
  enumerable: false,
  value: function(multiplier) {
    return Array(this.length * multiplier).fill(1).map((_, i) => this[i % this.length]);
  }
});

console.log([1,2,3].seqFill(3));
0 голосов
/ 04 июня 2018

Моей первой идеей было бы создать такую ​​функцию

let repeat = (array, numberOfTimes) => Array(numberOfTimes).fill(array).reduce((a, b) => [...a, ...b], [])
console.log(repeat(["a", "b", "c"], 3))

с использованием метода fill и уменьшение

В идеале, вместо уменьшения, вы можете использовать flatten но в браузерах пока нет поддержки

0 голосов
/ 04 июня 2018

Нет необходимости в какой-либо библиотеке, вы можете использовать Array.from для создания массива массивов, которые вы хотите повторить, а затем сгладить с помощью [].concat и распределить:

const makeRepeated = (arr, repeats) =>
  [].concat(...Array.from({ length: repeats }, () => arr));
  
console.log(makeRepeated([1, 2, 3], 2));

В новых браузерах вы можете использовать Array.prototype.flat вместо [].concat(...:

const makeRepeated = (arr, repeats) =>
  Array.from({ length: repeats }, () => arr).flat();
  
console.log(makeRepeated([1, 2, 3], 2));
...