在 JavaScript 中分区

IT技术 javascript list
2021-01-21 17:06:04

请考虑一个数组,例如:

arrayAll = [1,2,3,4,5,6,7,8,9]

是否有一个包可以进行分区以获得:

arrayALLPartionned = [[1,2,3],[4,5,6],[7,8,9]]

我可以看到如何使用 for 循环执行此操作,但如果存在“预制”函数,我将不胜感激。

6个回答

我认为你将不得不使用 for 循环,不知道任何内置函数......

试试这个功能:

function splitarray(input, spacing)
{
    var output = [];

    for (var i = 0; i < input.length; i += spacing)
    {
        output[output.length] = input.slice(i, i + spacing);
    }

    return output;
}
删除了额外的 for 循环 - 感谢您指出这一点
2021-03-22 17:06:04
这与接受的答案一样简单,并且不依赖于任何外部库。+1
2021-03-26 17:06:04
使用slice可以避免一个循环。
2021-04-08 17:06:04

这是一个递归解决方案:

function partition(array, n) {
  return array.length ? [array.splice(0, n)].concat(partition(array, n)) : [];
}    

这利用了Array#splice破坏性删除指定项目的事实,并将它们作为函数值返回。请注意,这将破坏输入数组,使其为空

如果使用Underscore.js,您可以使用groupBy()values()

function partition(items, size) {
    var result = _.groupBy(items, function(item, i) {
        return Math.floor(i/size);
    });
    return _.values(result);
}

(这在 CoffeeScript 中没那么难看。)

jsFiddle:http : //jsfiddle.net/MW3BS/

请注意,Underscore.js 现在有一个分区函数:underscorejs.org/#partition
2021-03-27 17:06:04
该分区函数仅将数组一分为二。
2021-04-08 17:06:04

另一种解决方案,没有外部库:

function partition(items, size) {
    var p = [];
    for (var i=Math.floor(items.length/size); i-->0; ) {
        p[i]=items.slice(i*size, (i+1)*size);
    }
    return p;
}

演示:http : //jsfiddle.net/dystroy/xtHXZ/

太好了,我认为它在某种程度上对应于我在 Mathematica 中使用“收获和播种”。再次感谢您。
2021-03-18 17:06:04
此解决方案不会考虑剩余部分:在您的小提琴中,如果您使用 4 作为大小运行它,您将错过最后一个元素
2021-03-20 17:06:04
如果这个答案没有平均分成,它会截断结果 size
2021-03-31 17:06:04
感谢您的关注 !你介意解释一下 "-->" 的用法吗?我以前从未见过这种语法。
2021-04-05 17:06:04
这只是意味着“递减 i 并将递减后的值与 0 进行比较”。这就像做i--和之后比较一样i>0以这种方式循环的有趣之处在于您不必多次评估最大范围值,因为>0可以在一次操作中计算。我并不是说你真的必须这样做才能快速编写代码,这不是那么重要,但这是我的习惯。
2021-04-11 17:06:04

我已将此解决方案添加到@dystroy 的 jspref 中,它的运行速度似乎是其他解决方案的两倍。编辑:在 Safari 和 Chrome 但不是 Firefox

这是功能风格的解决方案,可添加到此处的答案组合中。

它是一个被调用的高阶函数toPartitions,它返回下划线的 reduce 方法或本机数组 reduce 方法的回调。

用法示例:

[1,2,3,4,5,6,7,8,9].reduce( toPartitions( 3 ), [] );

功能:

function toPartitions ( size ) {
    var partition = [];
    return function ( acc, v ) {
        partition.push( v );
        if ( partition.length === size ) {
            acc.push( partition );
            partition = [];
        }
        return acc;
    };
}

与 Clojure 的分区一样,当元素不足时,它不会包含尾分区。

在您的示例中,您可以执行以下操作:

arrayALLPartionned = arrayAll.reduce( toPartitions( 3 ), [] ) );

如果您不想将其与 一起使用reduce,而只想使用一个接受数组和分区大小的函数,您可以执行以下操作:

function partition ( arr, size ) {
    return arr.reduce( toPartitions( size ), [] );
}

因此,解决方案将是:

arrayALLPartionned = partition( arrayAll, 3 );
这是一个很酷的解决方案。我唯一的疑虑是这不会有效地处理输入数组不能被分区大小整除的情况。例如,调用partition(arrayAll, 4)将返回两个分区,而最后一个值 ,9则不存在。解决这个问题的方法是在if条件中:if (partition.length === size || index === list.length - 1) { /* ... */ }当然,一个更定制的解决方案可能是包含一个额外的参数(例如withRemainder)来指示用户是否想要输出中的剩余分区。
2021-04-01 17:06:04