Jak podzielić długą tablicę na mniejsze tablice za pomocą JavaScript


106

Mam tablicę e-maili (może to być tylko 1 e-mail lub 100 e-maili) i muszę wysłać tablicę z żądaniem ajax (które wiem, jak to zrobić), ale mogę wysłać tylko tablicę, która ma Zawiera 10 lub mniej e-maili. Więc jeśli istnieje oryginalna tablica 20 e-maili, będę musiała podzielić je na 2 tablice po 10 każda. lub jeśli w oryginalnej tablicy jest 15 e-maili, to 1 tablica 10 i druga tablica 5. Używam jQuery, jaki byłby najlepszy sposób na zrobienie tego?

Odpowiedzi:


201

Nie używaj jquery ... używaj zwykłego 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];

Możesz to zapętlić, aby uzyskać pożądane zachowanie.

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

To dałoby ci 10 elementów na raz ... jeśli masz 15 elementów, otrzymasz 1-10, 11-15, tak jak chciałeś.


9
Zwróć uwagę, że YOUR_ARRAY również zostanie zużyty (tablica to obiekty ...)
Claudio

Tak, po prostu to umieściłem, ponieważ a nie jest opisowy, a już napisałem ten przykład używając ... to jest całkowicie niepotrzebna linia kodu ... Chociaż to sprawia, że ​​myślę ... jeśli używam tego wzorca, możesz chcieć zrobić głęboką kopię do działającej tablicy, aby nie zakłócać oryginału
jyore

@junvar IDK, jeśli ten 1-liniowy działał w 2018 r. (poważnie wątpię, że tak się stało), ale dzisiaj nie działa. Nigdy nie należy mutować (tj. Usuwać elementów) tablicy podlegającej iteracji, odrzuca ona indeks, tzn. Po każdym usunięciu należy ją ponownie dopasować o liczbę usuwanych elementów, aby „przeskakiwała do przodu” i nie zużywała tablica całkowicie. Spróbuj
Drew Reese

111
var size = 10; var arrayOfArrays = [];
for (var i=0; i<bigarray.length; i+=size) {
     arrayOfArrays.push(bigarray.slice(i,i+size));
}
console.log(arrayOfArrays);

W przeciwieństwie splice(), slice()jest nieinwazyjne do oryginalnej tablicy.


1
to rozwiązanie jest lepsze
Maduekwe Pedro

38

Po prostu zapętl tablicę, łącząc ją, aż zostanie zużyta.



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

while (a.length > 0) {

  chunk = a.splice(0,3)

  console.log(chunk)

}

wynik


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



13

Zakładając, że nie chcesz niszczyć oryginalnej tablicy, możesz użyć takiego kodu, aby podzielić długą tablicę na mniejsze tablice, które możesz następnie powtórzyć:

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
}

7

Array.reduce może być nieefektywne w przypadku dużych tablic, szczególnie w przypadku operatora mod. Myślę, że czystszym (i prawdopodobnie łatwiejszym do odczytania) rozwiązaniem funkcjonalnym byłoby to:

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

6

Kolejna realizacja:

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 - To nie zmienia oryginalnej tablicy.

Lub, jeśli wolisz funkcjonalną, w 100% niezmienną (chociaż nie ma nic złego w mutowaniu w miejscu, jak to zrobiono powyżej) i samodzielną metodą:

function splitBy(size, list) {
  return list.reduce((acc, curr, i, self) => {
    if ( !(i % size)  ) {  
      return [
          ...acc,
          self.slice(i, i + size),
        ];
    }
    return acc;
  }, []);
}

5

Jako dodatek do użytkownika @ jyore odpowiedź , aw przypadku nadal chcesz zachować oryginalną tablicę:

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

4

Chciałbym również podzielić się moim rozwiązaniem. Jest trochę bardziej szczegółowy, ale też działa.

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

Wyjście (sformatowane):

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

3

Inna metoda:

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

Nie ma to wpływu na oryginalną tablicę, ponieważ kopia utworzona przy użyciu plasterka jest przekazywana do argumentu „this” mapy.


2

Kolejna implementacja, wykorzystująca Array.reduce (myślę, że to jedyna brakująca!):

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;
    }, []);
};

Jak wiele rozwiązań powyżej, ten jest nieniszczący. Zwracanie pustej tablicy, gdy rozmiar wynosi 0, to tylko konwencja. Jeśli ifblok zostanie pominięty, pojawi się błąd, który może być tym, czego chcesz.


1

Możesz spojrzeć na ten kod. Prosty i skuteczny.

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

Oto prosta jedna wkładka

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

Bardziej kompaktowy:

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

Jeśli potrzebujesz metody, która nie modyfikuje istniejącej tablicy, spróbuj tego:

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

nie zapomnij zrobić: newArr = [] zmienną lokalną
zgthompson

Odpowiedzi zawierające tylko kod są zwykle oznaczane, a następnie usuwane z powodu niskiej jakości. Czy mógłbyś skomentować, jak to rozwiązuje pierwotny problem?
Graham,

to nie działa, jeśli rozmiar porcji jest mniejszy niż rozmiar tablicy wejściowej.
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
Witamy w stackoverflow. Twoja odpowiedź poprawiłaby się, gdybyśmy dodali jakieś wyjaśnienie.
Simon.SA

0

jako funkcja

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

używać

arrayChunk(originalArray, 10) //10 being the chunk size.

0

używając rekurencji

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

Uwaga: istniejąca tablica, tj. MyArr, zostanie zmodyfikowana.


0

używając prototypu możemy ustawić bezpośrednio na klasę tablicową

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

wyjście dla zakresu 3

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

wyjście dla zakresu 4

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

Czy mógłbyś dodać opis?
ego
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.