比如$scope.colsNum=3,生成一个$scope._outArray=[[5],[5],[2]]这样的数组。这里是想把$scope.testArray生成一个嵌套的数组,这样也能实现,但觉得自己写的太啰嗦了,希望给一个更好的写法。
1 回答
拉莫斯之舞
TA贡献1820条经验 获得超10个赞
用 lodash
如果用 lodash,很简单,一个函数就搞定
const _ = require("lodash");const result = _.chunk(data, colsNum);console.log(result);
lodash 的 _.chunk() 源码
回答完这个问题之后我突然好奇 lodash 是怎么实现的,所以我去翻了下它的源码,其中最关键的一段是
while (index < length) { result[resIndex++] = baseSlice(array, index, (index += size)); }
可以看出来,它采用的是 slice 的思想,每次取一段出来放在新数组中。 slice 它调用的 baseSlice()
在 _baseSlice.js
中,对应 _.slice()
方法,,实现的功能和 Array.prototype.slice
一致。
这就有意思了,如果采用这种方式,就有办法使用函数式与法了——见自己写函数的第三个方法。
自己写函数
reduce
当然自己写也可以,之前回答某个问题的时候写过,再写一次,用 reduce
再稍加处理。
主要是保持两个数组,一个是结果数组,一个是当前组数组,不需要 i
变量,因为当前组数组的 length
就能取到数量信息。
function groupByCols(data, cols) { const r = data.reduce((r, t) => { r.current.push(t); if (r.current.length === cols) { r.list.push(r.current); r.current = []; } return r; }, { list: [], current: [] }); if (r.current.length) { r.list.push(r.current); } return r.list; }const result = groupByCols(data, colsNum);console.log(result);
forEach
其实 reduce
用在这里优势不明显,因为有最后一步处理,不能直接返回结果。所以用和你的方法类似的 forEach
改写
function groupByCols2(data, cols) { const list = []; let current = []; data.forEach(t => { current.push(t); if (current.length === cols) { list.push(current); current = []; } }); if (current.length) { list.push(current); } return list; }
slice + map 实现
为了函数式写法,可能有些计算不太好理解,先看代码
const result = Array.apply(null, { length: Math.ceil(data.length / cols) }).map((x, i) => { return data.slice(i * cols, i * cols + cols); });
Array.apply
是为了生成一个长度为 Math.ceil(data.length / cols)
的数组,这就是循环次数(Math.ceil()
用于保证有余数则进1)。
然后在循环次数内通过 slice()
分段取出来。
用 RxJs
RxJs 用于异步处理数据还是挺方便的,用它的 bufferCount()
解决这种问题
const Rx = require("rxjs");const out = Rx.Observable.from(data) .bufferCount(colsNum) .toArray() .do(console.log) .subscribe();
这种方法适合异步或者 callback 处理(上面 console.log
那里传入的你的数据处理函数。
添加回答
举报
0/150
提交
取消