विखंडू में विखंडन सरणी


515

मान लीजिए कि मेरे पास एक जावास्क्रिप्ट सरणी है जो निम्नलिखित है:

["Element 1","Element 2","Element 3",...]; // with close to a hundred elements.

सरणी को कई छोटे सरणियों में सरणी को विभाजित करने (विभाजित करने) के लिए क्या उपयुक्त होगा, जो कहता है, इसके 10 तत्व हैं?


यह भी देखें कि अंडरस्कोर.जेएस (साथ ही जुड़े प्रश्नों में कई
डुप्ले


24
के लिए lodash उपयोगकर्ताओं, अपने लिए देख रहे हैं _.chunk
उलिसे बीएन

2
मैंने बस कोशिश की const chunk = (arr, n) => arr.length ? [arr.slice(0, n), ...chunk(arr.slice(n), n)] : []जो अच्छी और छोटी है, लेकिन लगता है कि करीब १५६० × तक @ AymKdn के १,००० तत्वों के लिए उत्तर, और १० elements५, × तक १०,००० तत्वों के लिए!
जू

यदि आपको अंतिम चंक के न्यूनतम आकार की भी आवश्यकता है, तो यहां विकल्प हैं: stackoverflow.com/questions/57908133/…
Ahmet Cetin

जवाबों:


640

Array.slice विधि, शुरुआत, मध्य, या जो कुछ भी प्रयोजनों आप की आवश्यकता के लिए एक सरणी के अंत से एक टुकड़ा निकाल सकते हैं मूल सरणी बदले बिना।

var i,j,temparray,chunk = 10;
for (i=0,j=array.length; i<j; i+=chunk) {
    temparray = array.slice(i,i+chunk);
    // do whatever
}

19
याद रखें कि यह chunkहोने के खिलाफ जोर देने के लिए एक उपयोग समारोह है 0। (अनंत लूप)
स्टीवन लू

19
नहींं, आखिरी हिस्सा दूसरों की तुलना में छोटा होना चाहिए।
ब्लेज़ेमॉन्गर

7
@Blazemonger, वास्तव में! अगली बार मैं वास्तव में निष्कर्ष निकालने के लिए कूदने से पहले खुद को आजमाऊंगा। मैंने (गलत तरीके से) मान लिया है कि array.slice में एक इनपुट पास करना जो कि सरणी की सीमा से अधिक है, एक समस्या होगी, लेकिन यह बिल्कुल सही काम करता है!
रसकी

55
एक-लाइनर्स (श्रृंखला प्रेमियों के लिए) : const array_chunks = (array, chunk_size) => Array(Math.ceil(array.length / chunk_size)).fill().map((_, index) => index * chunk_size).map(begin => array.slice(begin, begin + chunk_size));
Константин Ван

8
आपको j की आवश्यकता क्यों है? पहले मुझे लगा कि यह एक अनुकूलन है, लेकिन यह वास्तव में (i = 0; i <array.length; i ++) {} के लिए की तुलना में धीमी है
एलेक्स

149

Dbaseman द्वारा एक उत्तर से संशोधित: https://stackoverflow.com/a/10456344/711085

Object.defineProperty(Array.prototype, 'chunk_inefficient', {
  value: function(chunkSize) {
    var array = this;
    return [].concat.apply([],
      array.map(function(elem, i) {
        return i % chunkSize ? [] : [array.slice(i, i + chunkSize)];
      })
    );
  }
});

console.log(
  [1, 2, 3, 4, 5, 6, 7].chunk_inefficient(3)
)
// [[1, 2, 3], [4, 5, 6], [7]]


मामूली परिशिष्ट :

मुझे यह इंगित करना चाहिए कि उपरोक्त उपयोग करने के लिए नहीं (सुरुचिपूर्ण मेरे दिमाग में) वर्कअराउंड है Array.map। यह मूल रूप से निम्नलिखित कार्य करता है, जहां ~ संघनन है:

[[1,2,3]]~[]~[]~[] ~ [[4,5,6]]~[]~[]~[] ~ [[7]]

यह नीचे की विधि के रूप में एक ही स्पर्शोन्मुख चलने का समय है, लेकिन शायद खाली सूची बनाने के कारण एक बदतर निरंतर कारक है। निम्नानुसार इसे फिर से लिखा जा सकता है (ज्यादातर ब्लेज़मॉन्गर की विधि के समान है, यही वजह है कि मैंने मूल रूप से यह उत्तर प्रस्तुत नहीं किया है):

अधिक कुशल विधि:

// refresh page if experimenting and you already defined Array.prototype.chunk

Object.defineProperty(Array.prototype, 'chunk', {
  value: function(chunkSize) {
    var R = [];
    for (var i = 0; i < this.length; i += chunkSize)
      R.push(this.slice(i, i + chunkSize));
    return R;
  }
});

console.log(
  [1, 2, 3, 4, 5, 6, 7].chunk(3)
)


आजकल मेरा पसंदीदा तरीका उपरोक्त है, या निम्न में से एक है:

Array.range = function(n) {
  // Array.range(5) --> [0,1,2,3,4]
  return Array.apply(null,Array(n)).map((x,i) => i)
};

Object.defineProperty(Array.prototype, 'chunk', {
  value: function(n) {

    // ACTUAL CODE FOR CHUNKING ARRAY:
    return Array.range(Math.ceil(this.length/n)).map((x,i) => this.slice(i*n,i*n+n));

  }
});

डेमो:

> JSON.stringify( Array.range(10).chunk(3) );
[[1,2,3],[4,5,6],[7,8,9],[10]]

या यदि आप एक Array.range फ़ंक्शन नहीं चाहते हैं, तो यह वास्तव में सिर्फ एक-लाइनर (फुल को छोड़कर) है:

var ceil = Math.ceil;

Object.defineProperty(Array.prototype, 'chunk', {value: function(n) {
    return Array(ceil(this.length/n)).fill().map((_,i) => this.slice(i*n,i*n+n));
}});

या

Object.defineProperty(Array.prototype, 'chunk', {value: function(n) {
    return Array.from(Array(ceil(this.length/n)), (_,i)=>this.slice(i*n,i*n+n));
}});

41
एह, मैं प्रोटोटाइप के साथ खिलवाड़ करने से बचूँगा क्योंकि शीतलता की भावना आपको chunkफ़ंक्शन को कॉल करने से मिलती है, जो वास्तव में आपके द्वारा जोड़े जा रहे अतिरिक्त जटिलता को प्रभावित नहीं करता है और अंतर्निहित प्रोटोटाइप के साथ गड़बड़ करने वाले सूक्ष्म कीड़े पैदा कर सकते हैं।
गॉर्डन गुस्ताफ़सन

12
वह उनके साथ खिलवाड़ नहीं कर रहा है, वह उन्हें Arrays के लिए बढ़ा रहा है। मैं समझता हूं कि कभी भी Object.prototype को छूना नहीं है क्योंकि यह सभी ऑब्जेक्ट्स (सब कुछ) पर बुलबुला होगा लेकिन इस ऐरे विशिष्ट फ़ंक्शन के लिए मुझे कोई समस्या नहीं दिखाई देती है।
rlemon

बहुत यकीन है कि हालांकि array.map(function(i)नहीं होना चाहिएarray.map(function(elem,i)
निगेल एन्जिल

3
मोज़िला देव साइट पर संगतता चार्ट के आधार पर, IE9 + के लिए Array.map। सावधान रहे।
मिकेल डी

फ़्लोटिंग पास करने के लिए सावधान रहें - 7.5 प्रकार की संख्या - अप्रत्याशित चांस के लिए सीसा
Gal Bracha

103

यहां ईएस 6 संस्करण का उपयोग कम किया गया है

var perChunk = 2 // items per chunk    

var inputArray = ['a','b','c','d','e']

var result = inputArray.reduce((resultArray, item, index) => { 
  const chunkIndex = Math.floor(index/perChunk)

  if(!resultArray[chunkIndex]) {
    resultArray[chunkIndex] = [] // start a new chunk
  }

  resultArray[chunkIndex].push(item)

  return resultArray
}, [])

console.log(result); // result: [['a','b'], ['c','d'], ['e']]

और आप आगे के नक्शे को बदलने / परिवर्तनों को कम करने के लिए तैयार हैं। आपका इनपुट ऐरे बरकरार है


यदि आप कम लेकिन कम पठनीय संस्करण पसंद करते हैं, तो आप concatउसी अंतिम परिणाम के लिए मिश्रण में कुछ छिड़क सकते हैं :

inputArray.reduce((all,one,i) => {
   const ch = Math.floor(i/perChunk); 
   all[ch] = [].concat((all[ch]||[]),one); 
   return all
}, [])

यह सबसे घनीभूत घोल की तरह लगता है। ChunkIndex क्या है = Math.floor (index / perChunk) हो रहा है? क्या यह औसत है?
मुझ-

5/2 = 2.5और Math.floor(2.5) = 2इसलिए सूचकांक 5 के साथ आइटम बाल्टी 2 में रखा जाएगा
आंद्रेई आर

धन्यवाद आंद्रेई आर। अह तो यह 0 के माध्यम से कदम - 2। तो क्या यह मठ शब्दों में कहा जाता है? मुझे लगता है कि मेरी बात यह है कि मैंने कभी भी प्रत्येक स्लाइस के सूचकांक को प्राप्त करने के लिए सूचकांक / 2 को हर सूचकांक में विभाजित करने के लिए नहीं सोचा होगा। इसलिए मैं इसके चारों ओर अपना सिर लपेटने की कोशिश कर रहा हूं क्योंकि मैं वास्तव में इसे पसंद करता हूं लेकिन इसे मठ के संदर्भ में पूरी तरह से नहीं समझता हूं। मैं आमतौर पर कुल संख्या का औसत पाने के लिए ऐसा करता हूं लेकिन यह अलग दिखता है।
मुझ-मुझ

अन्य समाधानों की तुलना में यह समाधान अक्षम है क्योंकि आपको प्रत्येक तत्व पर पुनरावृति करने की आवश्यकता है।
जेपी डे ला टोरे

आप सही हैं @JPdelaTorre, यह संभवतः समाधान के रूप में कुशल नहीं है जो स्लाइस सरण देता है, लेकिन आप यहाँ बालों को विभाजित कर रहे हैं। सूचीबद्ध अधिकांश उत्तर उस परिभाषा के अकुशल होंगे।
आंद्रेई आर

102

देशी प्रोटोटाइप के साथ मर्किंग से बचने की कोशिश करें, जिसमें Array.prototype भी शामिल है, अगर आपको नहीं पता कि आपके कोड (3 पार्टी, सहकर्मी, बाद की तारीख में, आदि) का उपभोग कौन करेगा।

प्रोटोटाइप को सुरक्षित रूप से विस्तारित करने के तरीके हैं (लेकिन सभी ब्राउज़रों में नहीं) और विस्तारित प्रोटोटाइप से बनाई गई वस्तुओं का सुरक्षित रूप से उपभोग करने के तरीके हैं, लेकिन अंगूठे का बेहतर नियम कम से कम आश्चर्य के सिद्धांत का पालन ​​करना और इन प्रथाओं से पूरी तरह से बचना है।

यदि आपके पास कुछ समय है, तो इस विषय के बारे में अच्छी चर्चा के लिए, एंड्रयू ड्यूपॉन्ट के JSConf 2011 की बात करें, "सब कुछ परवान चढ़ा हुआ है: विस्तृत बिल्ट-इन"

लेकिन सवाल पर वापस, जबकि ऊपर के समाधान काम करेंगे, वे अत्यधिक जटिल हैं और अनावश्यक कम्प्यूटेशनल ओवरहेड की आवश्यकता है। यहाँ मेरा समाधान है:

function chunk (arr, len) {

  var chunks = [],
      i = 0,
      n = arr.length;

  while (i < n) {
    chunks.push(arr.slice(i, i += len));
  }

  return chunks;
}

// Optionally, you can do the following to avoid cluttering the global namespace:
Array.chunk = chunk;

25
"मूल प्रोटोटाइप के साथ टकराव से बचें" नए जेएस डेवलपर्स को एक अस्थायी मिलना चाहिए, अगर स्थायी नहीं, तो इस वाक्यांश का टैटू।
जैकब डाल्टन

2
मैं वर्षों से जावास्क्रिप्ट का उपयोग कर रहा हूं और बहुत अधिक कॉलिंग फ़ंक्शन पर प्रोटोटाइप के साथ परेशान करने के लिए बिना किसी समय के बगल में बिताता हूं, कभी भी संशोधित नहीं करता जैसे आप कुछ लोगों को करते हैं।
1984

2
मेरी नज़र में सबसे अच्छा सुझाव, समझने में सबसे सरल और कार्यान्वयन में, बहुत-बहुत धन्यवाद!
ओल्गा फार्बर ने

1
@JacobDalton मुझे लगता है कि यह सभी विश्वविद्यालयों की गलती है। लोगों को लगता है कि OOP का इस्तेमाल हर जगह होना चाहिए। इसलिए वे "सिर्फ एक समारोह बनाने" से डरते हैं। वे इसे किसी चीज के अंदर रखना सुनिश्चित करना चाहते हैं। भले ही यह उचित न हो। यदि कोई डॉट नोटेशन नहीं है, तो कोई "आर्किटेक्चर" नहीं है।
घुमान

51

मैंने jsperf.com में विभिन्न उत्तरों का परीक्षण किया। परिणाम वहां उपलब्ध है: https://web.archive.org/web/20150909134228/https://jsperf.com/chunk-mtds

और सबसे तेज कार्य (और IE8 से काम करता है) यह एक है:

function chunk(arr, chunkSize) {
  var R = [];
  for (var i=0,len=arr.length; i<len; i+=chunkSize)
    R.push(arr.slice(i,i+chunkSize));
  return R;
}

1
इस बेंचमार्क को बनाने के लिए धन्यवाद @AymKdn: यह इतना मददगार था! मैं ब्याह के दृष्टिकोण का उपयोग कर रहा था और इसने मेरे क्रोम v70 ब्राउज़र को 884432 के चंक साइज़ में क्रैश कर दिया। आपके सुझाए गए "स्लाइस" दृष्टिकोण के साथ, मेरा कोड अब ब्राउज़र की "रेंडर" प्रक्रिया को क्रैश नहीं करता है। :)
बेनी नेउगेबॉयर

34

मैं ब्याह विधि का उपयोग करना पसंद करूंगा :

var chunks = function(array, size) {
  var results = [];
  while (array.length) {
    results.push(array.splice(0, size));
  }
  return results;
};

16
इस ब्याह समाधान के साथ सावधान रहना चाहिए क्योंकि यह मूल सरणी को संशोधित करता है, इसलिए साइड इफेक्ट्स को स्पष्ट रूप से दस्तावेज करना सुनिश्चित करें।
bdrx

3
इसके बजाय स्लाइस का उपयोग करें
mplungjan

@mplungjan स्लाइस का उपयोग करते समय परिणाम बार-बार एक ही सरणी होगा। तो यह वास्तव में कुछ और संशोधनों के बिना एक ड्रॉप-इन प्रतिस्थापन नहीं है।
नीटोन्फिर

केवल एक चीज जो मैं इस उत्तर में जोड़ूंगा वह मूल सरणी का एक क्लोन है। मैं ईएस 6 के प्रसार ऑपरेटर के साथ ऐसा करूंगा। var clone = [...array]फिर उस क्लोन ऐरे के ऊपर लिंचिंग चेकिंग और स्पिलिंग करें।
MauricioLeal

1
या यदि आप ES6 सुविधाओं का उपयोग नहीं कर सकते हैं, तो आप बस array = array.slice()एक उथली प्रति बना सकते हैं।
3limin4t0r

34

ईसीएमए 6 में वन-लाइनर

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

new Array(Math.ceil(list.length / chuckSize)).fill().map(_ => list.splice(0,chuckSize))

9
यह मूल listसारणी को संशोधित करता है
जैका

6
.Slice () ...map((_,i) => list.slice(i*chuckSize,i*chuckSize+chuckSize))
जेम्स रॉबी

2
JSPerf पर यह अन्य उत्तरों की तुलना में बहुत अधिक परफॉर्मेंट है।
मीका हेनिंग

30

पुराना प्रश्न: नया उत्तर! मैं वास्तव में इस प्रश्न के उत्तर के साथ काम कर रहा था और उस पर एक मित्र ने सुधार किया था! तो यहाँ है:

Array.prototype.chunk = function ( n ) {
    if ( !this.length ) {
        return [];
    }
    return [ this.slice( 0, n ) ].concat( this.slice(n).chunk(n) );
};

[1,2,3,4,5,6,7,8,9,0].chunk(3);
> [[1,2,3],[4,5,6],[7,8,9],[0]]

14
fyi, इस पद्धति का प्रदर्शन O (N ^ 2) है, इसलिए इसे कोड के प्रदर्शन-महत्वपूर्ण खंडों में या लंबे सरणियों के साथ उपयोग नहीं किया जाना चाहिए (विशेषकर, जब सरणी .lengthरंक-आकार से बहुत अधिक है n)। यदि यह एक आलसी भाषा थी (जावास्क्रिप्ट के विपरीत), यह एल्गोरिथ्म O (N ^ 2) समय से ग्रस्त नहीं होगी। उस ने कहा, पुनरावर्ती कार्यान्वयन सुरुचिपूर्ण है। आप संभवतः इसे किसी सहायक फ़ंक्शन को पहले परिभाषित करके प्रदर्शन को बेहतर बनाने के लिए संशोधित कर सकते हैं array,position, जिस पर फिर से काम करता है : प्रेषण: Array.prototype.chunkरिटर्न [आपका सहायक कार्य] (...)
ninjagecko

मुझे अपनी आत्मा के साथ आशीर्वाद देने के लिए धन्यवाद सेंसैई कि मैं आज रात को चाटुकार रहा होगा
काट लिया

1
या ...var chunk = (arr, n) => { if ( !arr.length ) return []; return [ arr.slice( 0, n ) ].concat( chunk(arr.slice(n), n) ) }
एड विलियम्स

28

आजकल आप लॉश का उपयोग कर सकते हैं 'chunk' फंक्शन को एरे को छोटे एरेज़ में विभाजित करने के लिए https://lodash.com/docs#chunk अब लूप्स के साथ फील करने की आवश्यकता नहीं है!


3
मुझे ऐसा लगता है कि एसओ जावास्क्रिप्ट प्रश्नों के लिए अस्वीकरण होना चाहिए: क्या आपने दर्ज करने की कोशिश की है? बहुत ज्यादा पहली बात मुझे नोड या ब्राउज़र में शामिल है।
याकूब डाल्टन

20

कई उत्तर दिए गए हैं लेकिन यही वह है जो मैं उपयोग करता हूं:

const chunk = (arr, size) =>
  arr
    .reduce((acc, _, i) =>
      (i % size)
        ? acc
        : [...acc, arr.slice(i, i + size)]
    , [])

// USAGE
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
chunk(numbers, 3)

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

सबसे पहले, एक शेष के लिए जांचें जब सूचकांक को चंक आकार से विभाजित किया जाता है।

यदि कोई शेष है तो बस संचायक सरणी लौटाएं।

यदि कोई शेष नहीं है, तो सूचकांक चंक आकार से विभाज्य है, इसलिए मूल सरणी (वर्तमान सूचकांक पर शुरू) से एक टुकड़ा लें और इसे संचायक सरणी में जोड़ें।

तो, कम करने के प्रत्येक पुनरावृत्ति के लिए लौटा हुआ संचायक सरणी कुछ इस तरह दिखता है:

// 0: [[1, 2, 3]]
// 1: [[1, 2, 3]]
// 2: [[1, 2, 3]]
// 3: [[1, 2, 3], [4, 5, 6]]
// 4: [[1, 2, 3], [4, 5, 6]]
// 5: [[1, 2, 3], [4, 5, 6]]
// 6: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 7: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 8: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 9: [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]

पुनरावृत्तियों का अच्छा समाधान और अच्छा दृश्य प्रतिनिधित्व। मैं एक बहुत ही समान समाधान के साथ समाप्त हुआ जिसे मैंने एक उत्तर के रूप में पोस्ट किया: stackoverflow.com/a/60779547
mts knn

15

जनरेटर का उपयोग करना

function* chunks(arr, n) {
 for(let i = 0; i < arr.length; i += n) {
     yield(arr.slice(i, i+n));
     }
}
let someArray = [0,1,2,3,4,5,6,7,8,9]
console.log([...chunks(someArray, 2)]) // [[0,1],[2,3],[4,5],[6,7],[8,9]]


3
मुझे इस सवाल के सभी जवाबों पर आश्चर्य हुआ जो लगभग जनरेटर का उपयोग कर रहे थे या उन तरीकों से उपयोग कर रहे थे जो अधिक जटिल थे। इस समाधान के साथ अच्छा संक्षिप्तता और प्रदर्शन।
कीथ

14

ठीक है, चलो एक बहुत तंग के साथ शुरू करते हैं:

function chunk(arr, n) {
    return arr.slice(0,(arr.length+n-1)/n|0).
           map(function(c,i) { return arr.slice(n*i,n*i+n); });
}

जो इस तरह से प्रयोग किया जाता है:

chunk([1,2,3,4,5,6,7], 2);

तो फिर हम इस तंग reducer समारोह:

function chunker(p, c, i) {
    (p[i/this|0] = p[i/this|0] || []).push(c);
    return p;
}

जो इस तरह से प्रयोग किया जाता है:

[1,2,3,4,5,6,7].reduce(chunker.bind(3),[]);

चूँकि एक बिल्ली के बच्चे की मृत्यु हो जाती है, जब हम thisएक नंबर पर बंध जाते हैं, हम इसके बजाय इस तरह से मैन्युअल करी कर सकते हैं:

// Fluent alternative API without prototype hacks.
function chunker(n) {
   return function(p, c, i) {
       (p[i/n|0] = p[i/n|0] || []).push(c);
       return p;
   };
}

जो इस तरह से प्रयोग किया जाता है:

[1,2,3,4,5,6,7].reduce(chunker(3),[]);

फिर अभी भी बहुत तंग कार्य जो यह सब एक बार में करता है:

function chunk(arr, n) {
    return arr.reduce(function(p, cur, i) {
        (p[i/n|0] = p[i/n|0] || []).push(cur);
        return p;
    },[]);
}

chunk([1,2,3,4,5,6,7], 3);

IE8 में doesn't काम करता है।
नदीममन्न मोहम्मद

4
हा! मुझे बिल्ली का बच्चा टिप्पणी पसंद है। कोई अतिरिक्त रचनात्मक इनपुट के लिए खेद है :)
29er

मैं करूँगा (p[i/n|0] || (p[i/n|0] = [])), इसलिए यदि आप आवश्यक नहीं है, तो एक मूल्य प्रदान न करें ...
'15:

12

मैंने शुद्ध ES6 में एक सरल गैर-उत्परिवर्तन समाधान बनाने का लक्ष्य रखा। जावास्क्रिप्ट में ख़ासियतें मानचित्रण से पहले खाली सरणी को भरना आवश्यक बनाती हैं :-(

function chunk(a, l) { 
    return new Array(Math.ceil(a.length / l)).fill(0)
        .map((_, n) => a.slice(n*l, n*l + l)); 
}

पुनरावृत्ति वाला यह संस्करण सरल और अधिक सम्मोहक लगता है:

function chunk(a, l) { 
    if (a.length == 0) return []; 
    else return [a.slice(0, l)].concat(chunk(a.slice(l), l)); 
}

ES6 की हास्यास्पद कमजोर सरणी कार्य अच्छी पहेली के लिए बनाता है :-)


मैंने भी ऐसे ही अपना लिखा। यह अभी भी काम करता है अगर आप को दूर 0से fillहै, जो बनाता है fillदेखो थोड़ा और समझदार है, imho।
कॉर्ट ग्रोबबेलर

12

मुझे लगता है कि ES6 सिंटैक्स के साथ यह एक अच्छा पुनरावर्ती समाधान है:

const chunk = function(array, size) {
  if (!array.length) {
    return [];
  }
  const head = array.slice(0, size);
  const tail = array.slice(size);

  return [head, ...chunk(tail, size)];
};

console.log(chunk([1,2,3], 2));


9

इस https://www.npmjs.com/package/array.chunk के लिए एक npm पैकेज बनाया

var result = [];

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

जब एक TypedArray का उपयोग कर

var result = [];

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

@ A1rPun मेरा बुरा है, मैंने वहाँ टिप्पणी नहीं जोड़ी। हाँ, इसके लिए कोई sliceतरीका नहीं है TypedArray, हम subarrayइसके बजाय developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
zhiyelee

8

यदि आप EcmaScript संस्करण> = 5.1 का chunk()उपयोग करते हैं , तो आप array.reduce () जिसमें O (N) जटिलता का उपयोग कर के एक कार्यात्मक संस्करण को लागू कर सकते हैं :

function chunk(chunkSize, array) {
    return array.reduce(function(previous, current) {
        var chunk;
        if (previous.length === 0 || 
                previous[previous.length -1].length === chunkSize) {
            chunk = [];   // 1
            previous.push(chunk);   // 2
        }
        else {
            chunk = previous[previous.length -1];   // 3
        }
        chunk.push(current);   // 4
        return previous;   // 5
    }, []);   // 6
}

console.log(chunk(2, ['a', 'b', 'c', 'd', 'e']));
// prints [ [ 'a', 'b' ], [ 'c', 'd' ], [ 'e' ] ]

// nbrउपरोक्त प्रत्येक की व्याख्या :

  1. एक नया हिस्सा बनाएँ यदि पिछले मान, यानी पहले से लौटा हुआ हिस्सा, खाली है या यदि अंतिम पिछला हिस्सा chunkSizeसामान है तो
  2. मौजूदा विखंडू के सरणी में नया हिस्सा जोड़ें
  3. अन्यथा, वर्तमान चंक्स विखंडू के सरणी में अंतिम हिस्सा है
  4. वर्तमान मूल्य को चंक में जोड़ें
  5. विखंडू के संशोधित सरणी लौटें
  6. खाली सरणी पास करके कमी को प्रारंभ करें

के आधार पर करी chunkSize:

var chunk3 = function(array) {
    return chunk(3, array);
};

console.log(chunk3(['a', 'b', 'c', 'd', 'e']));
// prints [ [ 'a', 'b', 'c' ], [ 'd', 'e' ] ]

आप chunk()फ़ंक्शन को वैश्विक Arrayऑब्जेक्ट में जोड़ सकते हैं :

Object.defineProperty(Array.prototype, 'chunk', {
    value: function(chunkSize) {
        return this.reduce(function(previous, current) {
            var chunk;
            if (previous.length === 0 || 
                    previous[previous.length -1].length === chunkSize) {
                chunk = [];
                previous.push(chunk);
            }
            else {
                chunk = previous[previous.length -1];
            }
            chunk.push(current);
            return previous;
        }, []);
    }
});

console.log(['a', 'b', 'c', 'd', 'e'].chunk(4));
// prints [ [ 'a', 'b', 'c' 'd' ], [ 'e' ] ]


7
in coffeescript:

b = (a.splice(0, len) while a.length)

demo 
a = [1, 2, 3, 4, 5, 6, 7]

b = (a.splice(0, 2) while a.length)
[ [ 1, 2 ],
  [ 3, 4 ],
  [ 5, 6 ],
  [ 7 ] ]

a.splice (0, 2) एक [0..1] की सबरेरी को हटाता है और सबर्रे को एक [0..1] लौटाता है। मैं उन सभी सरणियों का एक सरणी बना रहा हूं
अर्पित जैन

2
मैं ब्याह के बजाय गैर-विनाशकारी टुकड़ा () विधि का उपयोग करने की सलाह देता हूं
Ash Blue

7
results = []
chunk_size = 10
while(array.length > 0){
   results.push(array.splice(0, chunk_size))
}

1
यह सुनिश्चित नहीं था कि यह डाउन-वोट क्यों किया गया था, लेकिन कोड कुछ स्पष्टीकरण का उपयोग कर सकता है।
jpaugh

2
क्योंकि ब्याह मूल सरणी के लिए विनाशकारी है।
धातुमास

7

निम्नलिखित ES2015 दृष्टिकोण एक फ़ंक्शन को परिभाषित करने और सीधे गुमनाम सरणियों पर काम करने के बिना काम करता है (उदाहरण चंक आकार 2 के साथ):

[11,22,33,44,55].map((_, i, all) => all.slice(2*i, 2*i+2)).filter(x=>x.length)

यदि आप इसके लिए किसी फ़ंक्शन को परिभाषित करना चाहते हैं, तो आप इसे निम्नानुसार कर सकते हैं ( Kaz ._ की टिप्पणी Blazemong's उत्तर पर सुधार ):

const array_chunks = (array, chunk_size) => array
    .map((_, i, all) => all.slice(i*chunk_size, (i+1)*chunk_size))
    .filter(x => x.length)

6

और इस विषय में मेरा योगदान होगा। मुझे लगता .reduce()है कि सबसे अच्छा तरीका है।

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);
        res = segment(arr,7);
console.log(JSON.stringify(res));

लेकिन .reduce()सभी arrकार्यों के माध्यम से चलने के बाद से उपरोक्त कार्यान्वयन बहुत कुशल नहीं है। एक और अधिक कुशल दृष्टिकोण (सबसे तेज़ अनिवार्यता समाधान के बहुत करीब) होगा, कम से कम (chunked) सरणी पर चलने के बाद से हम इसकी गणना पहले से कर सकते हैं Math.ceil(arr/n);। एक बार जब हमारे पास खाली परिणाम सरणी होती है, Array(Math.ceil(arr.length/n)).fill();तो बाकी की तरह इसमें सरणी के स्लाइस को मैप arrकरना होता है।

function chunk(arr,n){
  var r = Array(Math.ceil(arr.length/n)).fill();
  return r.map((e,i) => arr.slice(i*n, i*n+n));
}

arr = Array.from({length: 31},(_,i) => i+1);
res = chunk(arr,7);
console.log(JSON.stringify(res));



4

एक कार्यात्मक समाधान के लिए, रामदा का उपयोग कर :

popularProductsआपका इनपुट ऐरे कहां है, 5चंक साइज है

import splitEvery from 'ramda/src/splitEvery'

splitEvery(5, popularProducts).map((chunk, i) => {
// do something with chunk

})


4

ES6 एक-लाइन दृष्टिकोण Array.prototype reduceऔर pushविधियों के आधार पर :

const doChunk = (list, size) => list.reduce((r, v) =>
  (!r.length || r[r.length - 1].length === size ?
    r.push([v]) : r[r.length - 1].push(v)) && r
, []);

console.log(doChunk([0,1,2,3,4,5,6,7,8,9,10,11,12], 5));
// [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12]]

4

ES6 जेनरेटर संस्करण

function* chunkArray(array,size=1){
    var clone = array.slice(0);
    while (clone.length>0) 
      yield clone.splice(0,size); 
};
var a = new Array(100).fill().map((x,index)=>index);
for(const c of chunkArray(a,10)) 
    console.log(c);

constइसके बजाय उपयोग करें ।
Константин Ван

4

यह सबसे कुशल और सीधा-सीधा समाधान है जिसके बारे में मैं सोच सकता था:

function chunk(array, chunkSize) {
    let chunkCount = Math.ceil(array.length / chunkSize);
    let chunks = new Array(chunkCount);
    for(let i = 0, j = 0, k = chunkSize; i < chunkCount; ++i) {
        chunks[i] = array.slice(j, k);
        j = k;
        k += chunkSize;
    }
    return chunks;
}


4

यहाँ एक पुनरावर्ती समाधान है जो टेल कॉल ऑप्टिमाइज़ेशन है।

const splitEvery = (n, xs, y=[]) =>
  xs.length===0 ? y : splitEvery(n, xs.slice(n), y.concat([xs.slice(0, n)])) 

console.log(splitEvery(2, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))


4

एक और समाधान का उपयोग कर arr.reduce():

const chunk = (arr, size) => (
  arr.reduce((acc, _, i) => {
    if (i % size === 0) acc.push(arr.slice(i, i + size))
    return acc
  }, [])
)

// Usage:
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const chunked = chunk(numbers, 3)
console.log(chunked)

यह समाधान स्टीव होल्गाडो द्वारा समाधान के समान है । हालाँकि, क्योंकि यह समाधान सरणी प्रसार का उपयोग नहीं करता है और reducer फ़ंक्शन में नए सरणियों का निर्माण नहीं करता है, यह तेज़ है ( jsPerf परीक्षण देखें ) और अन्य समाधान की तुलना में विषय- अधिक पठनीय (सरल वाक्यविन्यास) है।

प्रत्येक nth पुनरावृत्ति पर (जहाँ n = size; पहली पुनरावृत्ति पर शुरू), संचायक सरणी ( acc) को सरणी के एक भाग के साथ जोड़ा जाता है (arr.slice(i, i + size) ) और फिर वापस आ जाता है। अन्य पुनरावृत्तियों में, संचायक सरणी को वापस लौटा दिया जाता है।

यदि sizeशून्य है, तो विधि एक खाली सरणी देता है। यदि sizeनकारात्मक है, तो विधि टूटे हुए परिणाम देती है। इसलिए, यदि आपके मामले में जरूरत है, तो आप नकारात्मक या गैर-सकारात्मक sizeमूल्यों के बारे में कुछ करना चाह सकते हैं ।


यदि आपके मामले में गति महत्वपूर्ण है, तो एक साधारण forलूप का उपयोग करने की तुलना में अधिक तेज़ होगा arr.reduce()( jsPerf परीक्षण देखें ), और कुछ इस शैली को और भी पठनीय पा सकते हैं:

function chunk(arr, size) {
  // This prevents infinite loops
  if (size < 1) throw new Error('Size must be positive')

  const result = []
  for (let i = 0; i < arr.length; i += size) {
    result.push(arr.slice(i, i + size))
  }
  return result
}

2

EDIT: @ mblase75 ने मुझे लिखते समय पहले के उत्तर में अधिक संक्षिप्त कोड जोड़ा, इसलिए मैं उसके समाधान के साथ जाने की सलाह देता हूं।

आप इस तरह कोड का उपयोग कर सकते हैं:

var longArray = ["Element 1","Element 2","Element 3", /*...*/];
var smallerArrays = []; // will contain the sub-arrays of 10 elements each
var arraySize = 10;
for (var i=0;i<Math.ceil(longArray.length/arraySize);i++) {
    smallerArrays.push(longArray.slice(i*arraySize,i*arraySize+arraySize));
}

arraySizeछोटे सरणियों की अधिकतम लंबाई बदलने के लिए मूल्य बदलें ।


2

यहाँ केवल पुनरावृत्ति और स्लाइस () का उपयोग करते हुए एक गैर-उत्परिवर्ती समाधान है।

const splitToChunks = (arr, chunkSize, acc = []) => (
    arr.length > chunkSize ?
        splitToChunks(
            arr.slice(chunkSize),
            chunkSize,
            [...acc, arr.slice(0, chunkSize)]
        ) :
        [...acc, arr]
);

तो बस इसे splitToChunks([1, 2, 3, 4, 5], 3)पाने के लिए उपयोग करें [[1, 2, 3], [4, 5]]

यहाँ आपके लिए एक पहेली है: https://jsfiddle.net/6wtrbx6k/2/

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.