如何用Lodash处理有序数组按列排序时的余数问题?
解决按列排序扁平数组时的余数问题
我明白你遇到的困扰了——用Lodash这类FP库的chunk方法处理有余数的数组时,按列合并后的结果总是不符合预期,对吧?问题的核心在于chunk是按行分块的逻辑:当数组元素总数不能被列数整除时,最后一个块的长度会比其他块短,这时候按列提取元素就会出现顺序混乱的情况。
正确的思路:从列的角度构建元素
要解决这个问题,我们需要换个思路:先确定总行数(向上取整数组长度/列数),然后从列索引出发,依次提取每一列的所有行元素,最后再扁平化集合。这样就能自动处理余数——有余数时,前面的列会比后面的列多一个元素,完全符合按列排序的预期。
用Lodash实现的具体代码
假设我们有一个按字母排序的数组,要分成3列后按列合并:
const _ = require('lodash'); // 示例数组 const sortedArr = ['A', 'B', 'C', 'D', 'E', 'F', 'G']; // 目标列数 const columnCount = 3; // 计算总行数(向上取整) const rowCount = Math.ceil(sortedArr.length / columnCount); // 按列提取并扁平化 const columnFlattened = _.flatMap(_.range(columnCount), colIndex => { // 遍历每一行,计算当前元素的索引 return _.times(rowCount, rowIndex => { const elementIndex = colIndex + rowIndex * rowCount; return sortedArr[elementIndex]; }).filter(_.identity); // 过滤掉超出数组长度的undefined项 }); console.log(columnFlattened); // 输出: ["A", "D", "G", "B", "E", "C", "F"]
封装成可复用函数
如果需要多次使用,可以把逻辑封装成一个函数:
const orderByColumns = (arr, columnNum) => { const rowNum = Math.ceil(arr.length / columnNum); return _.flatMap(_.range(columnNum), col => { return _.times(rowNum, row => arr[col + row * rowNum]).filter(Boolean); }); }; // 调用示例 console.log(orderByColumns(['A','B','C','D','E'], 2)); // 输出: ["A", "C", "E", "B", "D"]
为什么这个方法有效?
当数组元素总数不能被列数整除时,Math.ceil(arr.length / columnCount)会得到向上取整的总行数,这样前面的列(索引小的列)会优先包含多出来的元素。比如7个元素分3列,总行数是3,第0列会包含索引0、3、6(对应A、D、G),第1列包含1、4(B、E),第2列包含2、5(C、F),按列合并后完全符合预期的顺序。
而普通的chunk方法会把数组分成[['A','B','C'], ['D','E','F'], ['G']],按列提取时会得到A,D,B,E,C,F,G,显然和我们要的按列排序结果不符。
内容的提问来源于stack exchange,提问作者John Abraham
相关产品推荐
相关产品推荐

