Tia*_*ago 70 javascript arrays
想象一下,我有一个像这样的JS数组:
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
Run Code Online (Sandbox Code Playgroud)
我想要的是将该数组拆分为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]]
Run Code Online (Sandbox Code Playgroud)
对于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
Run Code Online (Sandbox Code Playgroud)
对于JS来说,我能想出的最好的解决方案是递归函数,但我不喜欢它,因为它复杂而丑陋.这个内部函数返回一个像这样的数组[1,2,3,null,4,5,6,null,7,8],然后我必须再次循环它并手动拆分它.(我的第一次尝试是返回这个:[1,2,3,[4,5,6,[7,8,9]],我决定使用空分隔符).
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));
}
Run Code Online (Sandbox Code Playgroud)
这是一个jsfiddle:http://jsfiddle.net/uduhH/
你会怎么做?谢谢!
geo*_*org 123
您可以切片"平衡"(子阵长度不同尽可能少)或'偶’(所有子阵列,但最后具有相同的长度):
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();
}Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
pim*_*vdb 11
我只是对算法进行了迭代实现: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;
}
Run Code Online (Sandbox Code Playgroud)
小智 9
function split(arr, n) {
var res = [];
while (arr.length) {
res.push(arr.splice(0, n));
}
return res;
}Run Code Online (Sandbox Code Playgroud)
我几年前给出的答案仅在originalArray.length<=时才有效numCols。您也可以使用下面类似的函数,但这会创建一个与手头问题不太匹配的布局(水平排序而不是垂直排序)。又名:[1,2,3,4]-> [[1,4],[2],[3]]。我知道这可能仍然提供价值,所以我将把它留在这里,但我推荐Senthe 的答案。
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
}
Run Code Online (Sandbox Code Playgroud)
老问题,但由于 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
}
Run Code Online (Sandbox Code Playgroud)
最后的for循环保证了所需的“列”数。
我认为使用拼接这种方式是最干净的:
splitToChunks(array, parts) {
let result = [];
for (let i = parts; i > 0; i--) {
result.push(array.splice(0, Math.ceil(array.length / i)));
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
例如,对于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
}, [[]])
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你!
编辑:因为有些人仍在评论这不能回答问题,因为我正在固定每个块的大小,而不是我想要的块数。这里是代码,解释了我要在注释部分中解释的内容:使用target.length。
target.reduce((memo, value, index) => {
if (index % 2 == 0 && index !== 0) memo.push([])
memo[memo.length - 1].push(value)
return memo
}, [[]])
Run Code Online (Sandbox Code Playgroud)
如果你碰巧事先知道你想要的块的大小,有一个非常优雅的 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]));Run Code Online (Sandbox Code Playgroud)
我发现这个符号非常有用,例如从Uint8ClampedArray.
一般来说,突变是一件坏事™。
这很好,干净,幂等。
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;
}
Run Code Online (Sandbox Code Playgroud)
[编辑添加]
这是调用者指定分区大小而不是要创建的分区数的另一种风格:
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 = [];
for (let i = 0; i < list.length; i += n) {
const partition = list.slice(i, i+n);
partitions.push( partition );
}
return partitions;
}
Run Code Online (Sandbox Code Playgroud)
如果您希望它是“平衡的”,使得各个块的长度差异不超过 1,那么只需要一点数学知识。
要以这种方式将 M 事物分配到 N 个桶中,我们需要首先确定 M / N 的商 Q 和余数 R。
让 Q 表示基本分区长度。R 将始终小于 N,并且是需要跨所有分区分布的多余项目的数量。因此,前 R 个分区将包含 Q+1 个项目,其余分区将包含 Q 个项目。
例如,要将 100 个项目的列表划分为 8 个桶,我们得到:
M = 10 N = 8 Q = 12 R = 4
所以我们会得到:
4 * 13 + 4 * 12 减少到 52+48,即 100。
这导致我们:
function partition(list = [], n = 1) {
const isPositiveInteger = Number.isSafeInteger(n) && n > 0;
if (!isPositiveInteger) {
throw new RangeError('n must be a positive integer');
}
const q = Math.floor( list.length / n );
const r = list.length % n;
let i ; // denotes the offset of the start of the slice
let j ; // denotes the zero-relative partition number
let len ; // denotes the computed length of the slice
const partitions = [];
for ( i=0, j=0, len=0; i < list.length; i+=len, ++j ) {
len = j < r ? q+1 : q ;
const partition = list.slice( i, i+len ) ;
partitions.push( partition ) ;
}
return partitions;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
53112 次 |
| 最近记录: |