JavaScript ile uzun bir dizi daha küçük dizilere nasıl bölünür


100

Bir dizi e-postam var (yalnızca 1 e-posta veya 100 e-posta olabilir) ve diziyi bir ajax isteği ile göndermem gerekiyor (nasıl yapılacağını bildiğim), ancak yalnızca İçinde 10 veya daha az e-posta var. Yani eğer 20 e-postadan oluşan orijinal bir dizi varsa, onları her biri 10'lu 2 diziye bölmem gerekecek. veya orijinal dizide 15 e-posta varsa, 1 10'luk dizi ve başka bir 5 dizisi varsa. jQuery kullanıyorum, bunu yapmanın en iyi yolu nedir?

Yanıtlar:


196

Jquery kullanmayın ... düz javascript kullanın

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

İstediğiniz davranışı elde etmek için bunu döngüye sokabilirsiniz.

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

Bu size bir seferde 10 element verir ... 15 element derseniz, 1-10, istediğiniz gibi 11-15 elde edersiniz.


9
YOUR_ARRAY'in de tüketileceğini unutmayın (dizi nesnelerdir ...)
Claudio

Evet, bunu sadece a tanımlayıcı olmadığı için koyuyordum ve örneği zaten a kullanarak yazmıştım ... bu tamamen gereksiz bir kod satırı ... Yine de, bu beni düşündürüyor ... eğer bu kalıbı kullanıyorsanız, orijinali bozmamak için çalışan bir diziye derin bir kopya yapmak isteyebilirsiniz
jyore

@junvar IDK eğer bu 1 astar 2018'de işe yarasaydı (gerçekten yaptığından şüpheliyim), ama bugün sefil bir şekilde başarısız oluyor. Üzerinde yinelenen bir diziyi asla mutasyona uğratmamalısınız (yani öğeleri kaldırmamalısınız), dizini atar, yani her kaldırıldıktan sonra, kaldırılan öğelerin sayısına göre yeniden ayarlanmalıdır, böylece "ileri atlar" ve tüketmez dizi tamamen. Deneyin
Drew Reese

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

Aksine splice(), slice()orijinal diziye zarar vermez.


1
bu çözüm daha iyi
Maduekwe Pedro

38

Sadece dizi üzerinde döngü yapın, hepsini tüketene kadar birleştirin.



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

while (a.length > 0) {

  chunk = a.splice(0,3)

  console.log(chunk)

}

çıktı


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



13

Orijinal diziyi yok etmek istemediğinizi varsayarsak, uzun diziyi daha sonra yineleyebileceğiniz daha küçük dizilere bölmek için aşağıdaki gibi bir kod kullanabilirsiniz:

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

Başka bir uygulama:

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 - Bu, orijinal diziyi değiştirmez.

Veya işlevsel,% 100 değişmez (yukarıda yapıldığı gibi yerinde mutasyona uğramada gerçekten kötü bir şey olmamasına rağmen) ve kendi kendine yeten bir yöntemi tercih ediyorsanız:

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 en çalışmasına ek olarak cevap ve durumda hala orijinal diziyi tutmak istiyorum:

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, özellikle mod operatörü ile büyük diziler için verimsiz olabilir. Bence daha temiz (ve muhtemelen okuması daha kolay) işlevsel bir çözüm şudur:

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

3

Diğer yöntem:

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

Bu, dilim kullanılarak yapılan bir kopya haritanın 'bu' argümanına aktarıldığı için orijinal diziyi etkilemez.


3

Ben de çözümümü paylaşmak isterim. Biraz daha ayrıntılı ama işe yarıyor.

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

Çıktı (biçimlendirilmiş):

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

2

Array.reduce kullanan başka bir uygulama (Bence eksik olan tek şey bu!):

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

Yukarıdaki birçok çözüm gibi, bu da tahribatsızdır. Boyut 0 olduğunda boş bir dizi döndürmek sadece bir kuraldır. Eğer ifblok atlanırsa istediğini olabilecek bir hataya olsun.


1

Bu koda bir göz atabilirsiniz. Basit ve Etkili.

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

İşte basit bir tek astar

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

Daha kompakt:

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

Mevcut diziyi değiştirmeyen bir yöntem istiyorsanız, şunu deneyin:

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

yapmayı unutma: newArr = [] yerel bir değişken
zgthompson

Yalnızca Kod Yanıtları genellikle işaretlenir ve ardından Düşük Kaliteli oldukları için silinir. Bunun orijinal sorunu nasıl çözdüğü konusunda biraz yorum yapabilir misiniz?
Graham

Bu, yığın boyutu giriş dizisi boyutundan küçükse çalışmaz.
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'a hoş geldiniz. Cevabınız bazı açıklamalar ekleyerek geliştirilebilir.
Simon.SA

0

işlev olarak

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

kullanmak

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

0

özyineleme kullanarak

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

Not: Var olan dizi, yani myArr değiştirilecektir.


0

prototip kullanarak doğrudan dizi sınıfına ayarlayabiliriz

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

aralık 3 için çıktı

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

aralık 4 için çıktı

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

Lütfen biraz açıklama ekleyebilir misiniz?
ego
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.