Як розділити довгий масив на менші масиви за допомогою JavaScript


100

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

Відповіді:


196

Не використовуйте 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 не є описовим, і я вже писав приклад, використовуючи ... це абсолютно непотрібний рядок коду ... Хоча, це змушує мене думати ... якщо використовувати цей шаблон, можливо, ви захочете зробити глибоку копію в робочий масив, щоб не порушити вам оригінал
jyore

@junvar IDK, якщо цей 1-лайнер запрацював у 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

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

const chunkArray = (arr, size) =>
  arr.length > size
    ? [arr.slice(0, size), ...chunkArray(arr.slice(size), size)]
    : [arr];

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

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

Це не впливає на оригінальний масив, оскільки копія, зроблена за допомогою фрагмента, передається в аргумент '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.