【问题标题】:Split JavaScript array in chunks using Lodash使用 Lodash 将 JavaScript 数组拆分成块
【发布时间】:2012-01-23 21:33:30
【问题描述】:

我需要将 JavaScript 数组拆分为 n 大小的块。

例如:给定这个数组

["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"]

n 等于4,输出应该是这样的:

[ ["a1", "a2", "a3", "a4"],
  ["a5", "a6", "a7", "a8"],
  ["a9", "a10", "a11", "a12"],
  ["a13"]
]

我知道纯 JavaScript solutions 可以解决这个问题,但由于我已经在使用 Lodash 我想知道 Lodash 是否为此提供了更好的解决方案。

编辑:

我创建了一个jsPerf test 来检查下划线解决方案的速度有多慢。

【问题讨论】:

    标签: javascript split functional-programming underscore.js lodash


    【解决方案1】:

    看看 lodash' chunkhttps://lodash.com/docs#chunk

    const data = ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"];
    const chunks = _.chunk(data, 3);
    console.log(chunks);
    // [
    //  ["a1", "a2", "a3"],
    //  ["a4", "a5", "a6"],
    //  ["a7", "a8", "a9"],
    //  ["a10", "a11", "a12"],
    //  ["a13"]
    // ]
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

    【讨论】:

    • 如果 lodash 和下划线都向后兼容的 API 会很有帮助
    • @Jonah 是的。以前的答案不再是最好的答案,因此为了读者,我更新了接受的答案:)
    【解决方案2】:

    对于基于下划线的解决方案,试试这个:

    var data = ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"];
    var n = 3;
    var lists = _.groupBy(data, function(element, index){
      return Math.floor(index/n);
    });
    lists = _.toArray(lists); //Added this to convert the returned object to an array.
    console.log(lists);
    

    使用链式包装方法,您可以将两个语句组合如下:

    var data = ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"];
    var n = 3;
    var lists = _.chain(data).groupBy(function(element, index){
      return Math.floor(index/n);
    }).toArray()
    .value();
    

    【讨论】:

    • 奇怪的是,Underscore 的 groupBy returns an object,而不是数组。不是破坏者——你得到基本相同的功能——但语义有点奇怪。 编辑: 哦,这样做是为了保持可链接性。还是很有趣的。
    • @Cesar Canassa:为了将来阅读该代码的开发人员,如果您将经常使用它,请考虑将其作为一个函数放入自定义库中,或者如果您不喜欢,请好好评论它t :)
    • @Jordan:没有意识到这一点。编辑了将对象转换为数组的答案。
    • 虽然我完全赞成将 Underscore 用于它最擅长的事情(并且 OP 要求使用基于 Underscore 的解决方案,因此 不是不值得的)和功能解决方案,似乎该解决方案引入了大量开销。正如@ajax33321 指出的那样,循环中的splice 仍然是一个三行代码,而且我猜它的性能更高。如果您的数组很短,这可能无关紧要,但如果您要处理数百或数千个项目,请注意其性能。
    • 这不再是最佳解决方案。请改用 chunk()
    【解决方案3】:

    一个可能更简单的表达式:

    const coll = [ "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9" ];
    const n = 2;
    const chunks = _.range(coll.length / n).map(i => coll.slice(i * n, (i + 1) * n));
    console.log(chunks);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

    【讨论】:

    • 比什么简单?答案应该是独立的。
    【解决方案4】:

    Underscore 从 1.9.0 版本开始原生支持 _.chunk()

    const data = ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"];
    const chunks = _.chunk(data, 4);
    console.log(chunks);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore.js"></script>

    【讨论】:

      【解决方案5】:

      试试这个更实用(例如,如果您想根据每个子数组中要成为容器的项目数量来拆分数组):

      function chunk(arr, start, amount){
          var result = [], 
              i, 
              start = start || 0, 
              amount = amount || 500, 
              len = arr.length;
      
          do {
              //console.log('appending ', start, '-', start + amount, 'of ', len, '.');
              result.push(arr.slice(start, start+amount));
              start += amount;
      
          } while (start< len);
      
          return result;
      };
      

      在你的情况下使用:

      var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],
          chunked = chunk(arr, 0, Math.floor(arr.length/3)); //to get 4 nested arrays
      
      console.log(chunked);
      

      还有一个案例:

      var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],
          chunked = chunk(arr, 0, 3); // to get 6 nested arrays each containing maximum of 3 items
      
      console.log(chunked);
      

      【讨论】:

      • 那个start 参数不是很实用恕我直言。您通常不想通过它;但是您总是需要指定块大小。最好交换这两个参数。
      • 为什么这是一个do while 循环?没有人想得到空的块。
      猜你喜欢
      • 1970-01-01
      • 2012-01-19
      • 1970-01-01
      • 1970-01-01
      • 2020-05-17
      • 2022-01-06
      相关资源
      最近更新 更多