文档章节

一道快速考察 Python 基础的面试题

张凯强-zkqiang
 张凯强-zkqiang
发布于 02/08 12:39
字数 930
阅读 1.4W
收藏 30

这是前一阵子群友发在群里的一道面试题,利用 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 这个方法后,面试官已经给你打了优秀,所以一定要熟悉这些数据对象的所有内置方法


本文属于原创,首发于微信公众号「面向人生编程」,如需转载请后台留言。

© 著作权归作者所有

张凯强-zkqiang

张凯强-zkqiang

粉丝 9
博文 6
码字总数 7033
作品 2
杭州
程序员
私信 提问
加载中

评论(2)

catroll
catroll
哈哈,我是搞复杂了一点

```py
def add_item(keys, value, dct):
key = keys.pop(0)
dct.setdefault(key, {})
if not keys:
dct[key] = value
else:
add_item(keys, value, dct[key])
return dct

new_data = {}
for key, value in data.items():
add_item(key.split('_'), value, new_data)
```
宇林木风
好!
Python基础面试,看这篇文章画重点吧,Python面试题No1

Python基础面试,看这篇文章画重点吧,Python面试题No1 为什么有这个系列的文章 一直想写一些更加基础的文章,但是总是想不到好的点子,最近到了就业季,一大堆学生面临就业了,正好,从Pyt...

优惠码领取
2019/04/29
0
0
面试不考算法考这些?大厂脑洞真的大!

不知道是不是觉得求职者面试压力还不够大,硅谷许多公司在面试时往往会另辟蹊径,给面试者抛出各种奇葩难题,以此来考验你到底符不符合他们的“胃口”。 这些莫名其妙的奇葩题,让无数求职者...

九章算法
02/07
0
0
BAT 七年经验,却抵不过外企面试的两道算法题?

整理| 琥珀 出品| AI科技大本营 又遇年底跳槽季,如果你曾在 BAT 等互联网大厂有过较为丰富的工作经验,想要换份工作,面试时会主要考虑哪些因素? 面试外企,却被两道算法题难住? 近日,一...

CSDN资讯
2019/01/07
0
0
一道神奇的Python面试题,你会吗?

关注公众号:「Python专栏」,后台回复「爬虫书籍」,即可获得2本Python爬虫相关的电子书 无意间,看到这么一道Python面试题:以下代码将输出什么? 脑中默默一想,这还用说么,肯定是: 最后...

上海小胖
2019/03/13
59
0
BAT七年经验,却抵不过外企面试的两道算法题?

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dQCFKyQDXYm3F8rB0/article/details/85889651 整理| 琥珀 出品| AI科技大本营 又遇年底跳槽季,如果你曾在 BA...

AI科技大本营
2019/01/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

佛山哪里可以开加油费发票-腾讯新闻网

佛山哪里可以开加油费发票【152 * 9б 28 * 21 б9】陈生,诚、信、合、作,保、真、售、后、保、障、长、期、有、效。adb的全称为Android Debug Bridg...

17054723543
14分钟前
24
0
佛山哪里可以开房租费发票-腾讯新闻网

佛山哪里可以开房租费发票【152 * 9б 28 * 21 б9】陈生,诚、信、合、作,保、真、售、后、保、障、长、期、有、效。adb的全称为Android Debug Bridg...

16510311845
15分钟前
29
0
佛山哪里可以开劳务费发票-腾讯新闻网

佛山哪里可以开劳务费发票【152 * 9б 28 * 21 б9】陈生,诚、信、合、作,保、真、售、后、保、障、长、期、有、效。adb的全称为Android Debug Bridg...

17035270105
15分钟前
27
0
佛山哪里可以开会议费发票-腾讯新闻网

佛山哪里可以开会议费发票【152 * 9б 28 * 21 б9】陈生,诚、信、合、作,保、真、售、后、保、障、长、期、有、效。adb的全称为Android Debug Bridg...

17035270092
15分钟前
17
0
佛山哪里可以开建材发票-腾讯新闻网

佛山哪里可以开建材发票【152 * 9б 28 * 21 б9】陈生,诚、信、合、作,保、真、售、后、保、障、长、期、有、效。adb的全称为Android Debug Bridge,...

17035270187
17分钟前
20
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部