Как разбить длинный массив на более мелкие с помощью 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 - как хотите.


9
Обратите внимание, что YOUR_ARRAY также будет израсходован (массив - это объекты ...)
Клаудио

Да, я просто вставил это, потому что a не является описательным, и я уже написал пример, используя ... это совершенно ненужная строка кода ... Хотя это заставляет меня думать ... если использовать этот шаблон, вы можете сделать глубокую копию в рабочий массив, чтобы не нарушить исходный
текст

@junvar IDK, если бы этот однострочник работал в 2018 году (я серьезно сомневаюсь, что это так), но сегодня он терпит неудачу. Вы никогда не должны изменять (т.е. удалять элементы) массив, по которому выполняется итерация, он сбрасывает индекс, то есть после каждого удаления он должен быть скорректирован на количество удаленных элементов, поэтому он «пропускает вперед» и не потребляет массив целиком. Попробуйте
Дрю Риз


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



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
}

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

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 карты.


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


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

не забудьте сделать: 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]]

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