जे सरणी को एन सरण में विभाजित करना


82

कल्पना कीजिए कि मेरे पास एक जेएस सरणी है:

var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];

मैं जो चाहता हूं, उस सरणी को एन छोटे सरणियों में विभाजित करना है। उदाहरण के लिए:

split_list_in_n(a, 2)
[[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11]]

For N = 3:
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11]]

For N = 4:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11]]

For N = 5:
[[1, 2, 3], [4, 5], [6, 7], [8, 9], [10, 11]]

अजगर के लिए, मेरे पास यह है:

def split_list_in_n(l, cols):
    """ Split up a list in n lists evenly size chuncks """
    start = 0
    for i in xrange(cols):
        stop = start + len(l[i::cols])
        yield l[start:stop]
        start = stop

जेएस के लिए, सबसे अच्छा सही समाधान जिसके साथ मैं आ सकता था एक पुनरावर्ती कार्य है, लेकिन मुझे यह पसंद नहीं है क्योंकि यह जटिल और बदसूरत है। यह आंतरिक फ़ंक्शन इस तरह की एक सरणी देता है [1, 2, 3, null, 4, 5, 6, null, 7, 8], और फिर मुझे इसे फिर से लूप करना होगा और इसे मैन्युअल रूप से विभाजित करना होगा। (मेरा पहला प्रयास इसे वापस कर रहा था: [१, २, ३, [४, ५, ६, [returning, returning, ९]]], और मैंने इसे अशक्त विभाजक के साथ करने का निर्णय लिया।

function split(array, cols) {
    if (cols==1) return array;
    var size = Math.ceil(array.length / cols);
    return array.slice(0, size).concat([null]).concat(split(array.slice(size), cols-1));
}

यहाँ एक jsfiddle है कि: http://jsfiddle.net/uduhH/

आप वह कैसे करेंगें? धन्यवाद!


2
संबंधित - stackoverflow.com/q/40166199/104380
vsync

1
आपका splitकार्य दूर नहीं है। आप nullदो सरणी आवरण जोड़कर व्यवसाय को निकाल सकते हैं : if (cols == 1) return [array]और return [array.slice(0, size)].concat(split(array.slice(size), cols-1))। मुझे लगता है कि यह पुनरावर्ती संस्करण यहां के अधिकांश उत्तरों की तुलना में अधिक पठनीय है।
स्कॉट सॉयट

जवाबों:


134

आप स्लाइस को "संतुलित" बना सकते हैं (सबरेज़ की लंबाई जितनी हो सके उतनी कम हो सकती है) या "सम"

function chunkify(a, n, balanced) {
    
    if (n < 2)
        return [a];

    var len = a.length,
            out = [],
            i = 0,
            size;

    if (len % n === 0) {
        size = Math.floor(len / n);
        while (i < len) {
            out.push(a.slice(i, i += size));
        }
    }

    else if (balanced) {
        while (i < len) {
            size = Math.ceil((len - i) / n--);
            out.push(a.slice(i, i += size));
        }
    }

    else {

        n--;
        size = Math.floor(len / n);
        if (len % size === 0)
            size--;
        while (i < size * n) {
            out.push(a.slice(i, i += size));
        }
        out.push(a.slice(size * n));

    }

    return out;
}


///////////////////////

onload = function () {
    function $(x) {
        return document.getElementById(x);
    }

    function calc() {
        var s = +$('s').value, a = [];
        while (s--)
            a.unshift(s);
        var n = +$('n').value;
        $('b').textContent = JSON.stringify(chunkify(a, n, true))
        $('e').textContent = JSON.stringify(chunkify(a, n, false))
    }

    $('s').addEventListener('input', calc);
    $('n').addEventListener('input', calc);
    calc();
}
<p>slice <input type="number" value="20" id="s"> items into
<input type="number" value="6" id="n"> chunks:</p>
<pre id="b"></pre>
<pre id="e"></pre>


आपका समाधान साफ-सुथरा है, यह वही काम करता है जो मेरा पुनरावर्ती समाधान करता है, लेकिन यह सब गड़बड़ है। धन्यवाद!
टियागो

3
एक आकर्षण की तरह काम करता है .. अच्छा समाधान
वरदान

हाय @georg, क्या आप इस लाइन को समझा सकते हैं: var size = Math.ceil((len - i) / n--);
dpg5000

@ dpg5000: जब अगला हिस्सा काटते हैं, तो इसका आकार शेष तत्वों len - iकी संख्या (शेष शेष की संख्या n--) ( )
georg

1
हाय @georg धन्यवाद। मैं यह सुनिश्चित करने के लिए इस कोड को कैसे संशोधित करूंगा कि सभी उप-सरणियां अंतिम सबरे के अलावा समान लंबाई की हैं (जब तक कि भाजक परिणाम नहीं बचेगा, जिसमें सभी उप-खंड समान होंगे)। मैं किसी भी मदद की सराहना करता हूं।
dpg5000

19

मुझे लगता है कि ब्याह का उपयोग करने का तरीका सबसे साफ है:

splitToChunks(array, parts) {
    let result = [];
    for (let i = parts; i > 0; i--) {
        result.push(array.splice(0, Math.ceil(array.length / i)));
    }
    return result;
}

उदाहरण के लिए, उदाहरण के लिए parts = 3, आप 1/3 भाग लेंगे, फिर शेष भाग 1/2, फिर शेष सरणी। Math.ceilयह सुनिश्चित करता है कि तत्वों की असमान संख्या के मामले में वे सबसे पहले विखंडू में जाएंगे।

(नोट: यह प्रारंभिक सरणी को नष्ट कर देता है।)


17

function split(array, n) {
  let [...arr]  = array;
  var res = [];
  while (arr.length) {
    res.push(arr.splice(0, n));
  }
  return res;
}


2
यह n = 5 और arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] के लिए अपेक्षित रूप से काम नहीं करता है।
टिआगो

1
यह n लंबाई में विभाजित नहीं है, केवल n लंबाई के उप-वर्ग में विभाजित नहीं है।
dpg5000

1
कृपया कुछ स्पष्टीकरण जोड़ें कि यह कोड ओपी की मदद क्यों करता है। यह एक उत्तर देने में मदद करेगा जिससे भविष्य के दर्शक सीख सकते हैं। अधिक जानकारी के लिए उत्तर कैसे देखें ।
हेरिटिक बंदर

12

मैंने अभी कलन विधि का पुनरावृत्ति कार्यान्वयन किया है: http://jsfiddle.net/ht22q/ । यह आपके परीक्षण मामलों को पास करता है।

function splitUp(arr, n) {
    var rest = arr.length % n, // how much to divide
        restUsed = rest, // to keep track of the division over the elements
        partLength = Math.floor(arr.length / n),
        result = [];

    for(var i = 0; i < arr.length; i += partLength) {
        var end = partLength + i,
            add = false;

        if(rest !== 0 && restUsed) { // should add one element for the division
            end++;
            restUsed--; // we've used one division element now
            add = true;
        }

        result.push(arr.slice(i, end)); // part of the array

        if(add) {
            i++; // also increment i in the case we added an extra element for division
        }
    }

    return result;
}

1
(यह उम्मीद के मुताबिक काम करता है, लेकिन मैं केवल एक उत्तर को सही मान सकता हूं) हाय! मदद के लिए धन्यवाद। बाकी का उपयोग करने के बारे में अच्छी सोच।
टियागो

7

आप इसे एक मैट्रिक्स में कम कर सकते हैं। नीचे दिया गया उदाहरण सरणी को विभाजित करता है (arr ) को दो-स्थिति सरणियों के मैट्रिक्स में हैं। यदि आप अन्य आकार चाहते हैं तो दूसरी पंक्ति में 2 मान बदलें:

target.reduce((memo, value, index) => {
  if (index % 2 === 0 && index !== 0) memo.push([])
  memo[memo.length - 1].push(value)
  return memo
}, [[]])

आशा है कि इससे सहायता मिलेगी!

संपादित करें: क्योंकि कुछ लोग अभी भी इस पर टिप्पणी कर रहे हैं, क्योंकि इस प्रश्न का उत्तर नहीं दिया गया है क्योंकि मैं प्रत्येक रंक की संख्या के बजाय जो मैं चाहता हूं, उसका आकार तय कर रहा था । यहाँ यह कोड आता है जो बताता है कि मैं क्या टिप्पणी अनुभाग में समझाने की कोशिश कर रहा हूं: का उपयोग करना target.length

// Chunk function

const chunk = (target, size) => {
  return target.reduce((memo, value, index) => {
    // Here it comes the only difference
    if (index % (target.length / size) == 0 && index !== 0) memo.push([])
    memo[memo.length - 1].push(value)
    return memo
  }, [[]])
}

// Usage

write(chunk([1, 2, 3, 4], 2))
write(chunk([1, 2, 3, 4], 4))

// For rendering pruposes. Ignore
function write (content) { document.write(JSON.stringify(content), '</br>') }


2
यह करने के लिए अच्छा और संक्षिप्त तरीका वाह! इसे प्यार करना! अच्छा काम! :-)
फिलिप मॉनेट

1
मुझे यह तकनीक पसंद है, लेकिन यह सवाल का जवाब नहीं दे रहा है। यह किसी भी प्रकार के x- आकार के विखंडू को लौटाता है, जबकि प्रश्न समान रूप से आकार के विखंडू के x राशि के लिए पूछ रहा था।
जोडी वॉरेन

3
इसे प्रेम करें !!! मैंने समान रूप से आकार के विखंडू function splitArr(arr, n) { return arr.reduce(function (a, i) { if (a[a.length - 1].length >= arr.length / n) { a.push([]) } a[a.length - 1].push(i) return a; }, [[]]) }
दाविद एंड्रियाज़िनी

3
निश्चित रूप से इस सवाल का जवाब नहीं है।
मैकडेलक्रूज़

1
संक्षिप्त और वास्तव में चतुर, इसे हल करने के लिए मेरा पसंदीदा तरीका और इस सरल पैटर्न के साथ पूरे मामले, धन्यवाद!
एडमंड तामस

5

अपडेट: 7/21/2020

मैंने कुछ साल पहले जो जवाब दिया है वह केवल तभी काम करता है अगर originalArray.length<= numCols। आप वैकल्पिक रूप से इस फ़ंक्शन के नीचे कुछ का उपयोग कर सकते हैं, लेकिन यह एक ऐसा लेआउट बनाएगा जो हाथ पर सवाल से मेल नहीं खाता (क्षैतिज छंटाई के बजाय क्षैतिज छंटाई)। उर्फ: [1,2,3,4]-> [[1,4],[2],[3]]। मैं समझता हूं कि यह अभी भी मूल्य प्रदान कर सकता है इसलिए मैं इसे यहां छोड़ दूंगा, लेकिन मैं सेंथे के उत्तर की सिफारिश करता हूं

function splitArray(flatArray, numCols){
  const newArray = []
  for (let c = 0; c < numCols; c++) {
    newArray.push([])
  }
  for (let i = 0; i < flatArray.length; i++) {
    const mod = i % numCols
    newArray[mod].push(flatArray[i])
  }
  return newArray
}

2017 से मूल उत्तर:

पुराना सवाल है, लेकिन चूंकि वनिला जेएस एक आवश्यकता नहीं है और इसलिए कई लोग इसे लॉश / चंक के साथ हल करने की कोशिश कर रहे हैं, और बिना गलती किए कि _.chunkवास्तव में क्या करता है, यहां एक संक्षिप्त + सटीक समाधान का उपयोग किया गया है lodash:

(स्वीकृत उत्तर के विपरीत, यह n कॉलम की गारंटी देता है, भले ही originalArray.length< numCols)

import _chunk from 'lodash/chunk'

/**
 * Split an array into n subarrays (or columns)
 * @param  {Array} flatArray Doesn't necessarily have to be flat, but this func only works 1 level deep
 * @param  {Number} numCols   The desired number of columns
 * @return {Array}
 */
export function splitArray(flatArray, numCols){
  const maxColLength = Math.ceil(flatArray.length/numCols)
  const nestedArray = _chunk(flatArray, maxColLength)
  let newArray = []
  for (var i = 0; i < numCols; i++) {
    newArray[i] = nestedArray[i] || []
  }
  return newArray
}

forअंत में पाश क्या "कॉलम" की वांछित संख्या की गारंटी देता है है।


यह तब विफल हो जाता है जब सरणी की लंबाई 4 और अंक 3 होती है। विभाजन के साथ प्रयास किया जाता है ([1, 2, 3, 4], 3) और यह वापस लौटता है [[1, 2], [3, 4], []]।
प्रतीक कुलश्रेष्ठ

आप बिल्कुल सही हैं @PratikKulshreshth मैं जवाब अपडेट कर दूंगा। किसी भी दिलचस्पी के लिए, मुझे सेंथे का जवाब सबसे अच्छा लगता है: stackoverflow.com/a/51514813/1322810
जोआओ

2

पुनरावर्ती दृष्टिकोण, परीक्षण नहीं किया गया।

function splitArray(array, parts, out) {
    var
        len = array.length
        , partLen

    if (parts < len) {
        partLen = Math.ceil(len / parts);
        out.push(array.slice(0, partLen));
        if (parts > 1) {
            splitArray(array.slice(partLen), parts - 1, out);
        }
    } else {
        out.push(array);
    }
}

2

एक और पुनरावर्ती काफी अच्छी तरह से काम करता है, यह कम बदसूरत है

function nSmaller(num, arr, sliced) {

    var mySliced = sliced || [];
    if(num === 0) {
        return sliced;
    }

    var len = arr.length,
        point = Math.ceil(len/num),
        nextArr = arr.slice(point);

    mySliced.push(arr.slice(0, point));
    nSmaller(num-1, nextArr, mySliced);

    return(mySliced);
}

2
function parseToPages(elements, pageSize = 8) {
    var result = [];
    while (elements.length) {
        result.push(elements.splice(0, pageSize));
    }
    return result;
}

3
कृपया उत्तर के रूप में कोड डंप न करें। एक स्पष्टीकरण जोड़ें कि यह प्रश्न की समस्या को कैसे संबोधित करता है।
मार्क रोटिटेवेल

2

यदि आप पहले से चाहते हैं कि चोक का आकार पता है, तो ऐसा करने का एक सुंदर ईएस 6 तरीका है:

const groupsOfFour = ([a,b,c,d, ...etc]) =>
  etc.length? [[a,b,c,d], ...groupsOfFour(etc)] : [[a,b,c,d]];
  
console.log(groupsOfFour([1,2,3,4,1,2,3,4,1,2,3,4]));

मुझे यह नोटेशन बहुत उपयोगी लगता है, उदाहरण के लिए आरजीए को पार्स करने से Uint8ClampedArray


सिवाय इसके कि यह n <4 के लिए विफल रहता है: अपेक्षित (और वांछित) के बजाय groupsOfFour( [ 1 ] )रिटर्न[ 1 , undefined, undefined, undefined ][ [1] ]
निकोलस कैरी

1

संभवतः क्लीनर दृष्टिकोण निम्नलिखित होगा (किसी अन्य पुस्तकालय का उपयोग किए बिना):

var myArray = [];
for(var i=0; i<100; i++){
  myArray.push(i+1);
}
console.log(myArray);

function chunk(arr, size){
  var chunkedArr = [];
  var noOfChunks = Math.ceil(arr.length/size);
  console.log(noOfChunks);
  for(var i=0; i<noOfChunks; i++){
    chunkedArr.push(arr.slice(i*size, (i+1)*size));
  }
   return chunkedArr;
}

var chunkedArr = chunk(myArray, 3);
console.log(chunkedArr);

मैंने अपनी खुद की एक सरणी बनाई है जिसे चंक करना है। आप यहां कोड पा सकते हैं

इसके अलावा हमारे पास लॉश लाइब्रेरी में एक विधि "चंक" है जो बहुत काम का है। उम्मीद है की वो मदद करदे


1
function splitArray(arr, numOfParts = 10){
        const splitedArray = []
        for (let i = 0; i < numOfParts;i++) {
            const numOfItemsToSplice = arr.length / 10;
            splitedArray.push(arr.splice(0, numOfItemsToSplice))
        }
        return splitedArray;
    }

1

म्यूटेशन, आम तौर पर बोल रहा है, एक बुरा बात ™।

यह अच्छा, स्वच्छ, और कोमल है।

function partition(list = [], n = 1) {
  const isPositiveInteger = Number.isSafeInteger(n) && n > 0;
  if (!isPositiveInteger) {
    throw new RangeError('n must be a positive integer');
  }

  const partitions = [];
  const partitionLength = Math.ceil(list.length / n);

  for (let i = 0; i < list.length; i += partitionLength) {
    const partition = list.slice(i, i+partitionLength);
    partitions.push( partition );
  }

  return partitions;
}

0

मैंने इसे इस तरह से बनाया है, यह काम करता है ...

function splitArray(array, parts) {
    if (parts< array.length && array.length > 1 && array != null) {
        var newArray = [];
        var counter1 = 0;
        var counter2 = 0;

        while (counter1 < parts) {
            newArray.push([]);
            counter1 += 1;
        }

        for (var i = 0; i < array.length; i++) {
            newArray[counter2++].push(array[i]);
            if (counter2 > parts - 1)
                counter2 = 0;
        }

        return newArray;
    } else 
        return array;
}

0

इस सरणी विभाजन के मेरे संस्करण की जाँच करें

// divide array
Array.prototype.divideIt = function(d){
    if(this.length <= d) return this;
    var arr = this,
        hold = [],
        ref = -1;
    for(var i = 0; i < arr.length; i++){
        if(i % d === 0){
            ref++;
        }
        if(typeof hold[ref] === 'undefined'){
            hold[ref] = [];
        }
        hold[ref].push(arr[i]);
    }

    return hold;
};

0

अगर आपको पता है कि child_arrays.length सेट करना चाहते हैं तो मुझे लगता है कि यह समाधान सबसे अच्छा है:

function sp(size, arr){ //size - child_array.length
    var out = [],i = 0, n= Math.ceil((arr.length)/size); 
    while(i < n) { out.push(arr.splice(0, (i==n-1) && size < arr.length ? arr.length: size));  i++;} 
    return out;
}

कॉल fn: sp (2, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) // 2 - child_arrat.length

उत्तर: [१, २], [३, ४], [५, ६], [2,,], [९, १०], [११]


0

यदि आप उपयोग कर सकते हैं lodashऔर एक कार्यात्मक प्रोग्रामिंग दृष्टिकोण चाहते हैं, तो यहां मैं आपके साथ आ रहा हूं:

const _ = require('lodash')

function splitArray(array, numChunks) {
  return _.reduce(_.range(numChunks), ({array, result, numChunks}, chunkIndex) => {
    const numItems = Math.ceil(array.length / numChunks)
    const items = _.take(array, numItems)
    result.push(items)
    return {
      array: _.drop(array, numItems),
      result,
      numChunks: numChunks - 1
    }
  }, {
    array,
    result: [],
    numChunks
  }).result
} 

0

उपरोक्त सभी ठीक काम कर सकते हैं, लेकिन क्या होगा अगर आपके पास associativeचाबियाँ के रूप में तार हैं?

objectKeys = Object.keys;

arraySplit(arr, n) {
    let counter = 0;
    for (const a of this.objectKeys(arr)) {
        this.arr[(counter%n)][a] = arr[a];
        counter++;
    }
}

0

मेरे पास एक ऐसा है जो मूल सरणी को नहीं बदलता है

function splitArray(array = [], nPieces = 1){
    const splitArray = [];
    let atArrPos = 0;
    for(let i = 0; i < nPieces; i++){
        const splitArrayLength  = Math.ceil((array.length - atArrPos)/ (nPieces - i));
        splitArray.push([]);
        splitArray[i] = array.slice(atArrPos, splitArrayLength + atArrPos);
        atArrPos += splitArrayLength;
    }
    return  splitArray
}


0

आप एक सरल पुनरावर्ती फ़ंक्शन का उपयोग कर सकते हैं

const chunkify = (limit, completeArray, finalArray = [])=>{
    if(!completeArray.length) return finalArray
    const a = completeArray.splice(0,limit);
    return chunkify(limit, completeArray, [...finalArray,a])
}



-1

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


1
सवाल पूछता है कि वनीला जेएस का उपयोग करके इसे कैसे हल किया जाए, जेएस पुस्तकालयों का उपयोग नहीं किया गया
टीजे

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

9
यह भी सवाल का जवाब नहीं है। वह एन एरेस चाहता है, एन एलीमेंट्स का एरे नहीं।
mAAdhaTTah 14

-3

यदि आप लॉश का उपयोग कर रहे हैं, तो आप इसे नीचे की तरह आसानी से प्राप्त कर सकते हैं:

import {chunk} from 'lodash';
// divides the array into 2 sections
chunk([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 2); // => [[1,2,3,4,5,6], [7,8,9,10,11]]

3
ये गलत है। _.chunkएन तत्वों के सरणियों को एन सरण नहीं बनाता है। आपके उदाहरण में पिछले एक में 2 तत्वों के साथ 6 सरणियों का आउटपुट होगा[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11]]
Vassilis Barzokas

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