一道快速考察 Python 基础的面试题
这是前一阵子群友发在群里的一道面试题,利用 Python 字典的特性,可以巧妙地使用精简代码达成完美解。
题目
将 data 转换成 new_data 这种形式,写出转换过程。
data = { 'a_b_h':1, 'a_b_i':2, 'a_c_j':3, 'a_d':4, 'a_c_k':5, 'a_e':6 } new_data = { 'a':{ 'b':{ 'h':1, 'i':2 }, 'c':{ 'j':3, 'k':5 }, 'd':4, 'e':6 } }
可以看出,转换的过程是将 key 的下划线进行拆分,然后下划线后边的字符嵌套在前面字符的值中。
感兴趣就打开 IDE,自己先试着解一下。
解题思路
你应该很快想到,主要思路是将下划线 split
后,然后依次使用字符生成内层字典,当达到最后一个字符时将数字作为值。
那么关键点在于,如何不断地获得内层字典去修改呢?实际本题就是考察你是否理解 Python 字典是引用传递这个特性。
什么是引用传递?我们知道 Python 中字典和列表对象都是可变对象,它们的变量传递给另一个变量后,改变对象元素会使得两个变量都会同时改变,比如:
new_data = {} tmp = {} new_data['a'] = tmp print(new_data) # {'a': {}} tmp['b'] = 1 print(new_data) # {'a': {'b': 1}}
如上,利用这个特性,将内层字典赋值给一个中间变量,然后改变这个中间变量,即可同步修改最终的 new_data 变量。
根据这个思路,初步代码如下:
data = { 'a_b_h':1, 'a_b_i':2, 'a_c_j':3, 'a_d':4, 'a_c_k':5, 'a_e':6 } new_data = {} for key, value in data.items(): keys = key.split('_') tmp = new_data last = len(keys) - 1 # 最后一个 key 的索引值 for i, k in enumerate(keys): if i == last: tmp[k] = value continue if k not in tmp: sub_tmp = {} tmp[k] = sub_tmp tmp = sub_tmp else: tmp = tmp[k]
这也是群友给出的第一版答案,这样写并没有多大问题,但是代码比较繁琐,肯定还有优化空间。
我们可以只使用一个中间变量即可,进一步优化:
for field, value in data.items(): keys = field.split('_') tmp = new_data last = len(keys) - 1 for i, k in enumerate(keys): if k not in tmp: tmp[k] = {} if i < last else value tmp = tmp[k] # 将内层 dict 传给 tmp
上面这个代码看似很简洁了,但是仍然还有两个 if 判断,如果不是使用了三元表达式的话,还会更多行。
所以可以进一步优化:
for field, value in data.items(): keys = field.split('_') tmp = new_data for k in keys[:-1]: tmp = tmp.setdefault(k, {}) tmp[keys[-1]] = value
我们省略掉了 last 来判断最后一个字符的索引,直接通过 keys[:-1]
避开最后一个字符,末尾再单独生成数字键值对。
这里还使用字典的一个内置方法 —— setdefault
。
dict.setdefault(key, default=None)
方法和 get
方法类似,只是如果键不存在于字典中,不仅会返回 default 参数的值,还同时会用该值自动生成一个键值对。
if k not in tmp: tmp[k] = {} v = tmp[k] # 等价于 v = tmp.setdefault(k, {})
最终我们使用了 6 行代码就解出该题,这也是接近最简代码。
如果使用字典引用的特性是合格的话,那么当你用出 setdefault
这个方法后,面试官已经给你打了优秀,所以一定要熟悉这些数据对象的所有内置方法。
本文属于原创,首发于微信公众号「面向人生编程」,如需转载请后台留言。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
02月08日云栖号头条:阿里:“防疫直采全球寻源平台”开通24小时,300万人参与
云栖号:https://yqh.aliyun.com第一手的上云资讯,不同行业精选的上云企业案例库,基于众多成功案例萃取而成的最佳实践,助力您上云决策! 今日最新云头条快讯: 阿里巴巴“防疫直采全球寻源平台”开通24小时,来自180个国家及地区的300万人参与防疫寻源物资接力,近700多家国内外商贸及生产企业提供了医供应信息;北京市司法局局长李富莹:按照北京市政府办公厅通知,宾馆、饭店、文化娱乐场所、商场超市、公共交通场站等人员密集场所的经营管理单位和地铁、公交等公共交通运营管理单位对未佩戴口罩的,应当进行劝阻。 一起来看最新的资讯: 阿里:“防疫直采全球寻源平台”开通24小时,300万人参与 阿里巴巴“防疫直采全球寻源平台”开通24小时,来自180个国家及地区的300万人参与防疫寻源物资接力,近700多家国内外商贸及生产企业提供了医供应信息。支付宝方面表示,平台上线了防疫物资信息服务平台,通过搜索同行程查询功能即可看到。目前,浙江省医疗物资保障组已发起第一项物资需求清单,其中包括医用口罩、防护服等。有别于其他物资信息平台,该平台利用蚂蚁区块链技术,由浙江省卫建委、经信厅主导,将对物资...
- 下一篇
Linux Lab 发布 v0.3 rc3,新增中文文档
Linux Lab 是一套用于 Linux 内核学习、开发和测试的即时实验室,可以极速搭建和使用,功能强大,用法简单! 可以用它来高效地学习处理器架构、Linux 内核、嵌入式 Linux 系统、C 语言编程、Linux 汇编、Shell 编程等。 Linux Lab Boot example 已经跃跃欲试了?!快来看看 Linux Lab:难以抗拒的十大理由,本次更新又增加了一大理由,快看下文! 如果您想学习 Linux 0.11 内核和 Linux X86 汇编语言,也可以访问另外两套 Lab,即 Linux 0.11 Lab 和 CS630 Qemu Lab。 版本更新 Linux Lab 先后于 6 月 29 日和 10 月 30 日发布了 v0.1 和 v0.2 正式版。 本次发布 v0.3 的第 3 个候选版本:v0.3 rc3, rc3 主要新增了中文文档,并通过函数模板进一步裁剪了代码,也修复了几处其他问题。 本次更新有 50 多笔提交,有三位贡献者提交了 PR。 $ git log --format='%aN' v0.3-rc2..HEAD | sort -u ...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- 设置Eclipse缩进为4个空格,增强代码规范
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- MySQL8.0.19开启GTID主从同步CentOS8
- Hadoop3单机部署,实现最简伪集群
- CentOS8编译安装MySQL8.0.19
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2整合Thymeleaf,官方推荐html解决方案