某司的手写题:行政区域层级控制

前言

  • 常网IT戳我呀!
  • 常网IT源码上线啦!
  • 本篇录入吊打面试官专栏,希望能祝君拿下Offer一臂之力,各位看官感兴趣可移步🚶。
  • 有人说面试造火箭,进去拧螺丝;其实个人觉得问的问题是项目中涉及的点 || 热门的技术栈都是很好的面试体验,不要是旁门左道冷门的知识,实际上并不会用到的。
  • 接下来请看某司的面试题:给你行政区域的数据,根据传入的层级返回对应的数据结构。

你一生追求的东西,

其实一开始就在。

一开始我就拥有世界上最珍贵的爱。

这一年慢慢才明白,

一生所求无非是爱与自由,

只是你后知后觉而已,

兜兜转转追寻一圈后,

才发现那把钥匙早已握在手中。

人无法同时拥有青春和对于青春的感受,

有些东西要靠失去才明证明它的珍贵。

一、问题剖析

现在我们有一份行政区划的数据(这是全部层级都有的);

需要根据传入的层级,如(只展示省,或者只展示省市)

来显示对应的数据结构。

二、结构

行政区划数据如下:

javascript 复制代码
[
  {
    "code": "44",
    "name": "广东省",
    "children": [
      {
        "code": "4401",
        "name": "广州市",
        "children": [
          {
            "code": "440103",
            "name": "荔湾区",
            "children": [
              {
                "code": "440103001",
                "name": "沙面街道"
              },
             
            ]
          }
        ]
      },
    ]
  },
  {
    "code": "11",
    "name": "北京市",
    "children":[
      ...
    ]
  },
]

然后传入层级。

如:只需要展示省市,后面的区、街道就不需要展示了。

要求我们在这份数据结构中处理。

三、简单粗暴

于是,我们简单粗暴,可以写出实习生都会写的代码:

javascript 复制代码
let provincesCitiesDistricts_tmp = data  // 行政区划数据
if (__config__.formatArea == 1) {
  // 1:省
  provincesCitiesDistricts_tmp.forEach((f) => {
    f.children = null;
  });
} else if (__config__.formatArea == 2) {
  // 2:省市
  provincesCitiesDistricts_tmp.forEach((f) => {
    Array.isArray(f.children) &&
      f.children.forEach((c) => {
      // 把市,后面的children赋为null
        c.children = null;
      });
  });
} else if (__config__.formatArea == 3) {
// 3:省市区
  provincesCitiesDistricts_tmp.forEach((f) => {
    Array.isArray(f.children) &&
      f.children.forEach((c) => {
        Array.isArray(c.children) &&
          c.children.forEach((c1) => {
            c1.children = null;
          });
      });
  });
} else if (__config__.formatArea == 4) {
// 4:省市区街道
  provincesCitiesDistricts_tmp.forEach((f) => {
    Array.isArray(f.children) &&
      f.children.forEach((c) => {
        Array.isArray(c.children) &&
          c.children.forEach((c1) => {
            Array.isArray(c1.children) &&
              c1.children.forEach((c2) => {
                c2.children = null;
              });
          });
      });
  });
}

obj["options"] = provincesCitiesDistricts_tmp;  // 这是最终的结果

面试官一看,这是摇摇头,说出你句经典的话,你回去等通知吧!

于是你,泪流满面的狂跑而去🚶。

于是你行者孙,第二天有备而来,并说道,这一次,我肯定能写出让你欣喜万分的来。

你左牵黄,右擎苍。

娓娓写来。

四:优解

我们停下来思考一下🧐,如果传入的是省市(控制到第二层),那只是将children循环到第二级的时候,将children赋空即可。

我们在回味一下之前写的这段代码。

发现都很类似的写法。

那么,上面这部分的代码可以用递归实现。

javascript 复制代码
// 设置children
const setChildren = (list, num = 0, index = 1) => {
  Array.isArray(list) &&
    list.forEach((f) => {
      // 只要这两个相等,则表示这一层的children需要赋空
      if (num == index) {
        f.children = null;
      } else {
        index++;
        setChildren(f.children, num, index);	// 递归调用
      }
    });
};

let provincesCitiesDistricts_tmp = data  // 行政区划数据
if (__config__.formatArea == 1) {
  provincesCitiesDistricts_tmp.forEach((f) => {
    f.children = null;
  });
} else if (__config__.formatArea == 2) {
  provincesCitiesDistricts_tmp.forEach((f) => {
    setChildren(f.children, 1);
  });
} else if (__config__.formatArea == 3) {
  provincesCitiesDistricts_tmp.forEach((f) => {
    setChildren(f.children, 2);
  });
} else if (__config__.formatArea == 4) {
  provincesCitiesDistricts_tmp.forEach((f) => {
    setChildren(f.children, 3);
  });
} else if (__config__.formatArea == 5) {
  provincesCitiesDistricts_tmp.forEach((f) => {
    setChildren(f.children, 4);
  });
}

obj["optionsString"] = provincesCitiesDistricts_tmp;

别急,一步一步来😁。

到这里,我们巧用递归优化了很多代码,我们看到if...else也是很恶心,接着优化代码:

javascript 复制代码
const setChildren = (list, num = 0, index = 1) => {
  Array.isArray(list) &&
    list.forEach((f) => {
      if (num == index) {
        f.children = null;
      } else {
        index++;
        setChildren(f.children, num, index);
      }
    });
};

let provincesCitiesDistricts_tmp = data  // 行政区划数据
if (__config__.formatArea == 1) {
  provincesCitiesDistricts_tmp.forEach((f) => {
    f.children = null;
  });
} else if (__config__.formatArea) {
  provincesCitiesDistricts_tmp.forEach((f) => {
    setChildren(f.children, __config__.formatArea - 1);
  });
}

obj["optionsString"] = provincesCitiesDistricts_tmp;

根据__config__.formatArea是多少层,控制行政区域到多少层显示。

五:深拷贝递归

🙋面试官:你小紫,对递归很熟?那你用递归实现一下深拷贝吧。

🙋🏻‍♂️这不是信手拈来的事情嘛!

javascript 复制代码
/**
* @description 提问:
* @description 1. 为什么使用WeakMap?
* @description 因为WeakMap是弱引用,可以防止递归进入死循环
* @description 2. 为什么使用obj.constructor()创建空对象?
* @description 构造函数新建一个空的对象,而不是使用{}或者[],这样可以保持原形链的继承
* @description 3. 有必要加上obj.hasOwnProperty(key)判断
* @description 判断属性是否来自原型链上,因为for..in..也会遍历其原型链上的可枚举属性
*
* @description 深拷贝(递归拷贝)
*
* @param {Array} obj 目标数组
* @param {WeakMap} [cache=new WeakMap()]
* @return {*}
* @memberof ArrayTool
*/
deepCopy1(obj, cache = new WeakMap()) {
    if (obj === null || typeof obj !== "object") return obj
    if (obj instanceof Date) return new Date(obj)
    if (obj instanceof RegExp) return new RegExp(obj)

    if (cache.has(obj)) return cache.get(obj) // 如果出现循环引用,则返回缓存的对象,防止递归进入死循环(Node的循环引用也返回缓存对象)
    let cloneObj = new obj.constructor() // 使用对象所属的构造函数创建一个新对象
    cache.set(obj, cloneObj) // 缓存对象,用于循环引用的情况

    for (let key in obj) {
      if (obj.hasOwnProperty(key)) {
        cloneObj[key] = this.deepCopy1(obj[key], cache) // 递归拷贝
      }
    }

    return cloneObj
}

这可以直接用在自己项目中的哦~

面试官摸了摸胡子,顺便摸了摸我那八块腹肌,明天来报到。

后记

其实这道题在实际项目中,行政区域很常见,行政区域数据无非是接口按需返回。

或者是在数据不变的情况下,数据结构放在前段项目中,由前段管理。

如果有其他更好的方法也欢迎评论区见,这里提供的只是诸多方法之一。

最后,祝君能拿下满意的offer。

我是Dignity_呱,来交个朋友呀,有朋自远方来,不亦乐乎呀!深夜末班车

👍 如果对您有帮助,您的点赞是我前进的润滑剂。

以往推荐

靓仔,说一下keep-alive缓存组件后怎么更新及原理?

面试官问我watch和computed的区别以及选择?

面试官问我new Vue阶段做了什么?

前端仔,快把dist部署到Nginx上

多图详解,一次性啃懂原型链(上万字)

Vue-Cli3搭建组件库

Vue实现动态路由(和面试官吹项目亮点)

项目中你不知道的Axios骚操作(手写核心原理、兼容性)

VuePress搭建项目组件文档

原文链接

juejin.cn/post/733758...

相关推荐
安忘2 小时前
LeetCode-274.H 指数
算法·leetcode·职场和发展
xxxmmc2 小时前
Leetcode 160 Intersection of Two Linked Lists
算法·leetcode·双指针
Y.O.U..2 小时前
美团AI面试总结
网络·面试·职场和发展
VincentStory3 小时前
分享一个项目中遇到的一个算法题
android·算法
姑苏洛言3 小时前
30天搭建消防安全培训小程序
前端
左钦杨4 小时前
Nuxt2 vue 给特定的页面 body 设置 background 不影响其他页面
前端·javascript·vue.js
yechaoa5 小时前
【揭秘大厂】技术专项落地全流程
android·前端·后端
MurphyChen5 小时前
🤯 一行代码,优雅的终结 React Context 嵌套地狱!
前端·react.js
逛逛GitHub5 小时前
推荐 10 个受欢迎的 OCR 开源项目
前端·后端·github
ylfhpy5 小时前
Java面试黄金宝典1
java·开发语言·算法·面试·职场和发展