# 原创:JavaScript 获取数组深度
计算数组的长度,给出以下例子,计算出数组的深度。
arrayDeepLevel([1, 2, [3, [1, [0]]]]),长度为3arrayDeepLevel([]),长度为0arrayDeepLevel([[[]]],长度为2arrayDeepLevel([0, [2], [2, [3]]]),长度为3
# 分析
默认最小是
0只计算是数组结构
第一反应过来,就是要递归循环。
所以起初构造了以下函数
let level = -1;
const arrayDeepLevel = function(array) {
  return function(data) {
    if (Array.isArray(data)) {
      for (let item of data) {
        if (Array.isArray(item)) {
          arrayDeepLevel(item);
        }
      }
      level++;
      return level;
    }
  };
};
通过验证,显示上面是成功的,但是,仅是单次使用,比如执行多次后,全局变量 level 就一直累加,显然不是我们想要的结果哦。
关键的一点就是,大函数只执行一次,递归是在内部构建,于是有了声明第二个函数的改造。
const arrayDeepLevel = function(array) {
  let level = -1;
  const recursion = function(data) {
    if (Array.isArray(data)) {
      for (let item of data) {
        if (Array.isArray(item)) {
          recursion(item);
        }
      }
      level++;
      return level;
    }
  };
  return recursion(array);
};
module.exports = arrayDeepLevel;
保证了多次执行的值都是被初始掉。
# 拓展以及延伸
曾在一个项目中处理过类似的问题。
简化后,通过移除非数组的元素,我们得到下面的结构比较:
[1,2,3,[5,6]]  => [[]]
[1,[2,[3,[]]]] => [[[[]]]]
...
我们通过这个结构 [[[[]]]],认为是一个字符串 '[[[[]]]]'。
为了更形象的描述 [ 始终对应 ] 构成一个 组合。
如下:
形象化:		"a,b,c,d      d1,c1,b1,a1"
对应的 		| | | |       |  |  |  |
原始字符 		[,[,[,[			  ], ], ], ]
序号:      0 1 2 3      4  5  6  7
于是得到:
a  index = 0
b  index = 1
c  index = 2
d  index = 3
d1 index = 4
c1 index = 5
b1 index = 6
a1 index = 7
得出并收集它们的索引值关系:
0  1,  2,  3
↓  ↓   ↓   ↓
4  5   6   7
经过一个 level 提取算法 (opens new window) 的实现,将得到一个有趣的现象:
公式:当前 index x 2 - value = 对应的 level
我们对 [0,1,2,3],通过算法转换如下:
| index | 0 | 1 | 2 | 3 | 
|---|---|---|---|---|
| value | 0 | 1 | 2 | 3 | 
index*2 - value |  0*2-0=0 | 1*2-1=1 | 2*2-2=2 | 3*2-3=1 | 
或许有人说,这个功能可能是个巧合,不妨看一下下面的:
已知,我们的结构是 [[[][]]],此时,左包围是对应索引与右括号的关系是 ,
0  1,  2,  4
↓  ↓   ↓   ↓
7  2   6   5
根据公式转换如下:
| index | 0 | 1 | 2 | 4 | 
|---|---|---|---|---|
| value | 0 | 1 | 2 | 3 | 
index*2 - value |  0*2-0=0 | 1*2-1=1 | 2*2-2=2 | 3*2-4=2 | 
直到这里,我们得出一个结论,只要知道左边的索引值,就可以对应的找到它合并为一个组合所在的索引值(即左边 [,找到匹配右边结束的 ]),以及它对应的 level。
这个算法被我应用于一款 HTML 转 Markdown 工具 Pyhtmd (opens new window),作为解析 HTML 列表元素 为 markdown 代码的核心支撑。
得到最大 level 的深度,只要 Math.max.apply(this,[0,1,2,2]) 即可。
下面是完整的代码实现:
const arrayDeepLevel = function(array) {
  console.time("get-array-deep-level-test-2==>");
  const arrayStr = JSON.stringify(array);
  let clearArrayStr = "";
  // 这里的正则没有写好
  arrayStr.replace(/(?:(\[|\]))/g, function($1) {
    clearArrayStr += $1;
    return $1;
  });
  const leftStrItems = [];
  // const rightStrItems = [];
  for (let i = 0; i < clearArrayStr.length; i++) {
    // start tag
    if (clearArrayStr[i] === "[") {
      leftStrItems.push(i);
    }
  }
  const leftMaps = {};
  for (let i = 0; i < leftStrItems.length; i++) {
    const item = leftStrItems[i];
    leftMaps[item] = i * 2 - item;
  }
  const levelArray = Object.values(leftMaps);
  console.timeEnd("get-array-deep-level-test-2==>");
  //  0.113037109375 ms,咋一看时间复杂度是O(n),但这里空间复杂度很高,加上其他多余的操作
  return Math.max.apply(this, levelArray);
};
module.exports = arrayDeepLevel;
it("4. ==> level:3", () => {
  // 因为原题目是元素的包括了自己,实际上这里最高二级,是针对外包围计算,而非元素
  expect(arrayDeepLevel([0, [1], [1, [2]]])).toBe(2);
});