Как разбить длинный массив на более мелкие с помощью JavaScript

100

У меня есть массив электронных писем (это может быть всего 1 электронное письмо или 100 писем), и мне нужно отправить массив с запросом ajax (который я знаю, как это сделать), но я могу отправить только массив, который имеет В нем 10 или меньше писем. Поэтому, если есть исходный массив из 20 писем, мне нужно будет разделить их на 2 массива по 10 сообщений в каждом. или если в исходном массиве 15 писем, то 1 массив из 10 и еще один массив из 5. Я использую jQuery, как лучше всего это сделать?

Билл
источник

Ответы:

195

Не используйте jquery ... используйте простой javascript

var a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];

var b = a.splice(0,10);

//a is now [11,12,13,14,15];
//b is now [1,2,3,4,5,6,7,8,9,10];

Вы можете зациклить это, чтобы получить желаемое поведение.

var a = YOUR_ARRAY;
while(a.length) {
    console.log(a.splice(0,10));
}

Это даст вам 10 элементов за раз ... если вы скажете 15 элементов, вы получите 1-10, а 11-15 - как хотите.

jyore
источник
9
Обратите внимание, что YOUR_ARRAY также будет израсходован (массив - это объекты ...)
Клаудио
Да, я просто вставил это, потому что a не является описательным, и я уже написал пример, используя ... это совершенно ненужная строка кода ... Хотя это заставляет меня думать ... если использовать этот шаблон, вы можете сделать глубокую копию в рабочий массив, чтобы не нарушить исходный
текст
@junvar IDK, если бы этот однострочник работал в 2018 году (я серьезно сомневаюсь, что это так), но сегодня он терпит неудачу. Вы никогда не должны изменять (т.е. удалять элементы) массив, по которому выполняется итерация, он сбрасывает индекс, то есть после каждого удаления он должен быть скорректирован на количество удаленных элементов, поэтому он «пропускает вперед» и не потребляет массив целиком. Попробуйте
Дрю Риз
107
var size = 10; var arrayOfArrays = [];
for (var i=0; i<bigarray.length; i+=size) {
     arrayOfArrays.push(bigarray.slice(i,i+size));
}
console.log(arrayOfArrays);

В отличие от splice(), slice()не разрушает исходный массив.

Blazemonger
источник
1
это решение лучше
Мадуэкве Педро
38

Просто переберите массив, соединяя его, пока он не будет полностью использован.



var a = ['a','b','c','d','e','f','g']
  , chunk

while (a.length > 0) {

  chunk = a.splice(0,3)

  console.log(chunk)

}

выход


[ 'a', 'b', 'c' ]
[ 'd', 'e', 'f' ]
[ 'g' ]

Клаудио
источник
33

Вы можете использовать lodash: https://lodash.com/docs

_.chunk(['a', 'b', 'c', 'd'], 2);
// → [['a', 'b'], ['c', 'd']]
Александр Парамонов
источник
13

Предполагая, что вы не хотите уничтожать исходный массив, вы можете использовать такой код, чтобы разбить длинный массив на более мелкие массивы, которые затем можно перебирать:

var longArray = [];   // assume this has 100 or more email addresses in it
var shortArrays = [], i, len;

for (i = 0, len = longArray.length; i < len; i += 10) {
    shortArrays.push(longArray.slice(i, i + 10));
}

// now you can iterate over shortArrays which is an 
// array of arrays where each array has 10 or fewer 
// of the original email addresses in it

for (i = 0, len = shortArrays.length; i < len; i++) {
    // shortArrays[i] is an array of email addresss of 10 or less
}
jfriend00
источник
6

Другая реализация:

const arr = ["H", "o", "w", " ", "t", "o", " ", "s", "p", "l", "i", "t", " ", "a", " ", "l", "o", "n", "g", " ", "a", "r", "r", "a", "y", " ", "i", "n", "t", "o", " ", "s", "m", "a", "l", "l", "e", "r", " ", "a", "r", "r", "a", "y", "s", ",", " ", "w", "i", "t", "h", " ", "J", "a", "v", "a", "S", "c", "r", "i", "p", "t"];

const size = 3; 
const res = arr.reduce((acc, curr, i) => {
  if ( !(i % size)  ) {    // if index is 0 or can be divided by the `size`...
    acc.push(arr.slice(i, i + size));   // ..push a chunk of the original array to the accumulator
  }
  return acc;
}, []);

// => [["H", "o", "w"], [" ", "t", "o"], [" ", "s", "p"], ["l", "i", "t"], [" ", "a", " "], ["l", "o", "n"], ["g", " ", "a"], ["r", "r", "a"], ["y", " ", "i"], ["n", "t", "o"], [" ", "s", "m"], ["a", "l", "l"], ["e", "r", " "], ["a", "r", "r"], ["a", "y", "s"], [",", " ", "w"], ["i", "t", "h"], [" ", "J", "a"], ["v", "a", "S"], ["c", "r", "i"], ["p", "t"]]

NB - Это не изменяет исходный массив.

Или, если вы предпочитаете функциональный, на 100% неизменяемый (хотя на самом деле нет ничего плохого в изменении на месте, как это сделано выше) и автономный метод:

function splitBy(size, list) {
  return list.reduce((acc, curr, i, self) => {
    if ( !(i % size)  ) {  
      return [
          ...acc,
          self.slice(i, i + size),
        ];
    }
    return acc;
  }, []);
}
Аурелио
источник
5

В качестве дополнения к @ jyore - х ответа , и в случае , если вы все еще хотите сохранить исходный массив:

var originalArray = [1,2,3,4,5,6,7,8];

var splitArray = function (arr, size) {

  var arr2 = arr.slice(0),
      arrays = [];

  while (arr2.length > 0) {
      arrays.push(arr2.splice(0, size));
  }

  return arrays;
}

splitArray(originalArray, 2);
// originalArray is still = [1,2,3,4,5,6,7,8];
Джастин
источник
5

Array.reduce может быть неэффективным для больших массивов, особенно с оператором mod. Я думаю, что более чистым (и, возможно, более легким для чтения) функциональным решением будет следующее:

const chunkArray = (arr, size) =>
  arr.length > size
    ? [arr.slice(0, size), ...chunkArray(arr.slice(size), size)]
    : [arr];
Tawnos178
источник
3

Другой способ:

var longArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var size = 2;

var newArray = new Array(Math.ceil(longArray.length / size)).fill("")
    .map(function() { return this.splice(0, size) }, longArray.slice());

// newArray = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]];

Это не влияет на исходный массив, поскольку копия, сделанная с использованием slice, передается в аргумент this карты.

AFurlepa
источник
3

Я тоже хотел бы поделиться своим решением. Он немного более подробный, но тоже работает.

var data = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];

var chunksize = 4;


var chunks = [];

data.forEach((item)=>{
  if(!chunks.length || chunks[chunks.length-1].length == chunksize)
  chunks.push([]);

  chunks[chunks.length-1].push(item);
});

console.log(chunks);

Вывод (отформатированный):

[ [ 1,  2,  3,  4],
  [ 5,  6,  7,  8],
  [ 9, 10, 11, 12],
  [13, 14, 15    ] ]
Филипе Николи
источник
2

Другая реализация с использованием Array.reduce (я думаю, что это единственное, чего не хватает!):

const splitArray = (arr, size) =>
{
    if (size === 0) {
        return [];
    }

    return arr.reduce((split, element, index) => {
        index % size === 0 ? split.push([element]) : split[Math.floor(index / size)].push(element);
        return split;
    }, []);
};

Как и многие вышеперечисленные решения, это неразрушающее. Возврат пустого массива при размере 0 - это просто соглашение. Если ifблок опущен, вы получите сообщение об ошибке, которое может быть именно тем, что вам нужно.

Альф
источник
1

Вы можете взглянуть на этот код. Просто и эффективно.

function chunkArrayInGroups(array, unit) {
var results = [],
length = Math.ceil(array.length / unit);

for (var i = 0; i < length; i++) {
    results.push(array.slice(i * unit, (i + 1) * unit));
}
 return results;
}

chunkArrayInGroups(["a", "b", "c", "d"], 2);
Субханкар
источник
1

Вот простой лайнер

var segment = (arr, n) => arr.reduce((r,e,i) => i%n ? (r[r.length-1].push(e), r)
                                                    : (r.push([e]), r), []),
        arr = Array.from({length: 31}).map((_,i) => i+1);
console.log(segment(arr,7));

Уменьшить
источник
1

Более компактный:

const chunk = (xs, size) =>
  xs.map((_, i) =>
    (i % size === 0 ? xs.slice(i, i + size) : null)).filter(Boolean);
    
// Usage:
const sampleArray = new Array(33).fill(undefined).map((_, i) => i);

console.log(chunk(sampleArray, 5));

Dzuc
источник
0

Если вам нужен метод, который не изменяет существующий массив, попробуйте следующее:

let oldArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
let newArray = [];
let size = 3; // Size of chunks you are after
let j = 0; // This helps us keep track of the child arrays

for (var i = 0; i < oldArray.length; i++) {
  if (i % size === 0) {
    j++
  }
  if(!newArray[j]) newArray[j] = [];
  newArray[j].push(oldArray[i])
}
Райан
источник
0
function chunkArrayInGroups(arr, size) {
    var newArr=[];

    for (var i=0; arr.length>size; i++){
    newArr.push(arr.splice(0,size));
    }
    newArr.push(arr.slice(0));
    return newArr;

}

chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6], 3);
Zgthompson
источник
не забудьте сделать: newArr = [] локальной переменной
zgthompson
Ответы только с кодом, как правило, помечаются, а затем удаляются как низкое качество. Не могли бы вы прокомментировать, как это решает исходную проблему?
Грэм
это не работает, если размер блока меньше размера входного массива.
r3wt
0
function chunkArrayInGroups(arr, size) {
    var newArr=[];

    for (var i=0; i < arr.length; i+= size){
    newArr.push(arr.slice(i,i+size));
    }
    return newArr;

}

chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6], 3);
Ридванулла Ибрагим
источник
2
Добро пожаловать в stackoverflow. Ваш ответ можно улучшить, добавив некоторые пояснения.
Simon.SA
0

как функция

var arrayChunk = function (array, chunkSize) {
            var arrayOfArrays = [];

            if (array.length <= chunkSize) {
                arrayOfArrays.push(array);
            } else {
                for (var i=0; i<array.length; i+=chunkSize) {
                    arrayOfArrays.push(array.slice(i,i+chunkSize));
                }
            }
            return arrayOfArrays;
        }

использовать

arrayChunk(originalArray, 10) //10 being the chunk size.
Клинт
источник
0

используя рекурсию

let myArr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
let size = 4; //Math.sqrt(myArr.length); --> For a n x n matrix
let tempArr = [];
function createMatrix(arr, i) {
    if (arr.length !== 0) {
      if(i % size == 0) {
        tempArr.push(arr.splice(0,size))
      } 
      createMatrix(arr, i - 1)
    }
}
createMatrix(myArr, myArr.length);
console.log(tempArr);

Примечание. Существующий массив, т.е. myArr, будет изменен.

Сиддхарт Ядав
источник
0

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

Array.prototype.chunk = function(n) {
  if (!this.length) {
    return [];
  }
  return [this.slice(0, n)].concat(this.slice(n).chunk(n));
};
console.log([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15].chunk(5));

АмитНайек
источник
0
const originalArr = [1,2,3,4,5,6,7,8,9,10,11];
const splittedArray = [];
  while (originalArr.length > 0) {
    splittedArray.push(originalArr.splice(0,range));  
  }

выход для диапазона 3

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

выход для диапазона 4

splittedArray === [[1,2,3,4][5,6,7,8][9,10,11]]
Haures Bogdan
источник
Не могли бы вы добавить описание?
эго