JS 배열을 N 배열로 분할
다음과 같은 JS 배열이 있다고 상상해보십시오.
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
내가 원하는 것은 그 배열을 N 개의 작은 배열로 나누는 것입니다. 예를 들면 :
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]]
Python의 경우 다음이 있습니다.
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
JS의 경우 내가 생각 해낼 수있는 가장 적합한 솔루션은 재귀 함수이지만 복잡하고 추악하기 때문에 마음에 들지 않습니다. 이 내부 함수는 [1, 2, 3, null, 4, 5, 6, null, 7, 8]과 같은 배열을 반환 한 다음 다시 반복하고 수동으로 분할해야합니다. (내 첫 번째 시도는 다음을 반환했습니다 : [1, 2, 3, [4, 5, 6, [7, 8, 9]]], 그리고 null 구분 기호를 사용하기로 결정했습니다).
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/
어떻게 하시겠습니까? 감사!
슬라이스를 "균형"(서브 레이의 길이가 가능한 한 작게 다름) 또는 "균등"(모든 하위 배열이지만 마지막은 동일한 길이)으로 만들 수 있습니다.
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>
알고리즘을 반복적으로 구현했습니다 : 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;
}
function split(arr, n) {
var res = [];
while (arr.length) {
res.push(arr.splice(0, n));
}
return res;
}
스플 라이스를 사용하는 것이 가장 깨끗하다고 생각합니다.
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
요소 수가 고르지 않은 경우 가장 빠른 청크로 이동합니다.
(참고 : 이것은 초기 배열을 파괴합니다.)
그것을 행렬로 줄일 수 있습니다. 아래 예제는 배열 ( 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>') }
오래된 질문이지만 vanillaJS는 요구 사항이 아니기 때문에 많은 사람들이 lodash / chunk로이 문제를 해결하려고 노력하고 있으며 _.chunk
실제로 수행 하는 작업을 착각하지 않고 lodash
다음 을 사용하는 간결하고 정확한 솔루션이 있습니다 .
(허용되는 답변과 달리 originalArray.length
< 하더라도 n 열을 보장합니다. 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
끝에 있는 루프는 원하는 "열"수를 보장합니다.
재귀 적 접근 방식, 테스트되지 않았습니다.
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);
}
}
또 다른 재귀는 아주 잘 작동하지만 덜 추합니다.
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);
}
아마도 더 깨끗한 접근 방식은 다음과 같을 것입니다 (다른 라이브러리를 사용하지 않음).
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);
나는 청크 될 내 자신의 배열을 만들었습니다. 여기 에서 코드를 찾을 수 있습니다.
또한 lodash 라이브러리에는 매우 유용한 방법 "chunk"가 있습니다. 도움이되는 희망
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;
}
function parseToPages(elements, pageSize = 8) {
var result = [];
while (elements.length) {
result.push(elements.splice(0, pageSize));
}
return result;
}
원하는 청크의 크기를 미리 알고 있다면 ES6의 매우 우아한 방법이 있습니다.
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]));
이 표기법은 예를 들어 RGBA를 Uint8ClampedArray
.
간단한 재귀 함수를 사용할 수 있습니다.
const chunkify = (limit, completeArray, finalArray = [])=>{
if(!completeArray.length) return finalArray
const a = completeArray.splice(0,limit);
return chunkify(limit, completeArray, [...finalArray,a])
}
이런 식으로 만들었습니다. 작동합니다 ...
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;
}
이 배열 분할의 내 버전을 확인하십시오.
// 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;
};
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
답변 : [1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11]
Just use lodash' chunk function to split the array into smaller arrays https://lodash.com/docs#chunk No need to fiddle with the loops anymore!
If you can use lodash
and would like a functional programming approach, here is what I come up with:
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
}
all above might work fine, but what if you have associative
array with strings as keys?
objectKeys = Object.keys;
arraySplit(arr, n) {
let counter = 0;
for (const a of this.objectKeys(arr)) {
this.arr[(counter%n)][a] = arr[a];
counter++;
}
}
I have one that doesn't alter original array
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
}
lodash chunk(array, Math.round(array.length / n))
If you are using lodash, you can achieve it fairly easily like below:
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]]
참고URL : https://stackoverflow.com/questions/8188548/splitting-a-js-array-into-n-arrays
'Program Tip' 카테고리의 다른 글
xampp에서 컬을 활성화하는 방법은 무엇입니까? (0) | 2020.11.13 |
---|---|
easy_install이 MySQLdb를 찾을 수없는 이유는 무엇입니까? (0) | 2020.11.13 |
필드를 비활성화하지 않고 사용자가 텍스트 필드에 입력하는 것을 방지하는 방법은 무엇입니까? (0) | 2020.11.12 |
Zipalign-명령을 찾을 수 없음-MAC 터미널 (0) | 2020.11.12 |
Laravel의 블레이드 템플릿을 사용하여 레이아웃에 변수를 어떻게 전달합니까? (0) | 2020.11.12 |