JavaScript 列表重构

来源:互联网 发布:php addslashes和gpc 编辑:程序博客网 时间:2024/05/20 04:45

最近碰到一个将矩阵转置(Transpose)的问题,有人会说这还不简单,写个函数就解决了:

function transpose(matrix) {    var ret = [];    for(var i in matrix)        for(var j in matrix[i]) {            ret[j] = ret[j] || [];            ret[j][i] = matrix[i][j];        }    return ret;}

Naive。

让我们用函数式的眼光重新分析这个问题。

这涉及了将矩阵压平(Flatten)、划分(Partition)的操作:

这些都属于列表重构(Restructuring)。

本质上,我们是先将整个矩阵给压平了(变成一维数组),然后再划分它们(变成二维数组)。

上面的命令式语言背后也体现了这样一个思想。

看看函数式实现:1

// 压平:依次将每个子数组连接起来即可。flatten = (matrix) => matrix.reduce((pre, cur) => pre.concat(cur), []);// 划分:将每个元素取模后扔到对应的位置即可。partition = (array, n) => array.reduce((pre, cur, i) => (pre[i % n] = pre[i % n] || []).push(cur) && pre, []);

好吧,单行的partition写得有点婊了。其实是这样的:

partition = (array, n) => array.reduce((pre, cur, i) => {    pre[i % n] = pre[i % n] || [];    pre[i % n].push(cur);    return pre;}, []);

然后将其组合成数组的转置:

transpose = (matrix) => partition(flatten(matrix), matrix[0].length);

什么?你不想要单独定义压平与划分?

可以,直接inline化,改写成transpose大礼包:

transpose = (matrix) => matrix.reduce((pre, cur) => pre.concat(cur), []).reduce((pre, cur, i) => (pre[i % matrix[0].length] = pre[i % matrix[0].length] || []).push(cur) && pre, []);

然后调用:

transpose([[1, 2, 3], [4, 5, 6]]); // [ [1, 4], [2, 5], [3, 6] ]

  1. 关于 数组的 reduce 方法可以参考我的另外一篇博文:# reduce ↩
0 0