三级菜单,按省、市、县三级做一个查询菜单,要求如下,
1.可逐级查询(比如输入山东省,跳出山东所有市,再输入青岛市,可展示青岛所有县)
2.输入b可以返回上一层,比如莱西一级,输入b返回上级青岛,再输入b返回山东。
3.输入q退出。
这个是上上期的三级菜单的题目。
后来呢,又学了文件读写的章节,然后题目又延伸了一下,延伸内容如下:
1.将三级菜单存入文本文件中
2.展示省市县,数据存在文本中;
3.对菜单实现增删改,删、改容易理解,增么,就是用户增加一个城市
第3条中的增乍一看挺简单,琢磨一下,要处理文本,还有编码貌似挺复杂的。不对,如果要删中间级咋整?这是一个坑啊,中间级必须先删光子级才允许删。。目前依旧是按照刚入门的基本语法来完成这个题目,这题目不难,但是写起来挺坑的,愣是写了100多行……
前两天的代码果然有问题,网上翻了一下,主要问题吧,是干了一件傻事,字典的增删改差,愣是被我做成了文本的增删改查。所以删减了三十行代码,现在看起来好了那么一点点。
代码中的district_database文档,就是txt文档,内容如下
{
'1001':'北京市',
'100101':'北京市辖区',
'10010101':'东城区',
'10010102':'西城区',
'10010103':'朝阳区',
'100102':'北京市县',
'10010201':'密云县',
'10010202':'延庆县',
'1002':'天津市',
'100201':'天津市辖区',
'10020102':'和平区',
'10020103':'河东区',
'10020104':'河西区',
'10020105':'南开区',
'10020106':'河北区',
'100202':'天津市县',
'10020203':'宁河县',
'10020201':'静海县',
'10020202':'蓟县',
}
#!/usr/bin/env python3.6
# -*- coding: utf-8 -*-
#__author__: Ed Frey
#Date: 18/8/2
current_layer_len = 4 #第一层省份编码长度是4位数
parent_layer = '10' #父层编码初始值取编码前2位,也就是10. 输入下一级城市时,城市编码增加2位,父层编码就是切片城市编码[:-2]
with open('district_database', 'r') as f:
menu = f.read()
menu = eval(menu)
while True:
current_layer = {key:value for key,value in menu.items() if len(key) == current_layer_len and key.startswith(parent_layer)}
#取出相应位数编码的城市。
print('The current layer of cities:')
for i in current_layer:
print(current_layer[i])
choice = input('Please input the district(press b/q/d/c/a to back or quit or delete or change or append):').strip()
if len(choice) == 0:continue
if choice in current_layer.values():
parent_layer = list(current_layer.keys())[list(current_layer.values()).index(choice)]
# print(parent_layer) 字典无序,转换成列表,然后根据输入的城市的序号,获取当前城市的编码
current_layer_len += 2
elif choice == 'b':#返回上一层
if current_layer_len-2:
current_layer_len -= 2
parent_layer = parent_layer[:-2]
elif choice == 'd':#删除当前城市(如有下级一并删除)
choice2=input('Please input the city you want to delete:'.strip())
if choice2 in current_layer.values():
for key in menu:
if menu[key] == choice2:
sub_code=key
break
sub_code2=[]
for key in menu:
if key.startswith(sub_code):
sub_code2.append(key)
#如果要删的城市有子集,要全部删掉,比如要删1002天津,那就把1002开头的所有下级城市,一并删除,那也就是要汇集这些城市的序号。
for code in sub_code2:
del menu[code]
continue
else:
print('invalid input!!!')
elif choice == 'c':#修改当前城市名称
choice2 = input('Please input the city you want to change:'.strip())
if choice2 in current_layer.values():
choice3 = input('Please input the result:'.strip())
for key in menu:
if menu[key] == choice2:
sub_code=key
break
menu[sub_code]=choice3
continue
else:
print('invalid input!!!')
elif choice == 'a':#增加新城市
choice2 = input('Please input the city you want to append current layer:'.strip())
if choice2 in current_layer.values():
print(f'{choice2} exists!!!')
else:
append_max_code = 0
for sub_code in current_layer:
if int(sub_code) > append_max_code:
append_max_code = int(sub_code) # 取当前层城市编码最大值
append_max_code += 1
#要增加一个新城市,同样,要编一个序号,取该级别下的最大序号,再加1,作为新城市的序号。
menu[str(append_max_code)]=choice2
continue
elif choice == 'q':#退出并存盘数据。
with open('district_database', 'w') as f:
f.write(str(menu))# 按q退出时,再将最终结果写入文本中。
break
else:
print('invalid input,try again please')
那网上大神的代码也贴一下供大家参考:
链接https://www.cnblogs.com/Yongzyw/p/8654746.html
#初始化 将menu存入磁盘中
# menu = {'北京':{
# '朝阳':{
# '国贸':{
# 'CICC':{},
# 'HP':{},
# '渣打银行':{},
# 'CCTV':{}
# },
# '望京':{
# '陌陌':{},
# '奔驰':{},
# '360':{}
# },
# '三里屯':{
# '优衣库':{},
# 'apple':{}
# }
# },
# '昌平':{
# '沙河':{
# '老男孩':{},
# '阿泰包子':{}
# },
# '天通苑':{
# '链家':{},
# '我爱我家':{}
# },
# '回龙观':{}
# },
# '海淀':{
# '五道口':{
# '谷歌':{},
# '网易':{},
# 'Souhu':{},
# 'Sogo':{},
# '快手':{}
# },
# '中关村':{
# 'youku':{},
# 'Iqiyi':{},
# '汽车之家':{},
# '新东方':{}
# }
# }
# },
# '上海':{
# '浦东':{
# '陆家嘴':{
# 'CICC':{},
# '高盛':{},
# '摩根':{}
# },
# '外滩':{}
# },
# '闵行':{},
# '静安':{}
# },
# '山东':{
# '济南':{},
# '德州':{
# '乐陵':{
# '丁务镇':{},
# '城区':{}
# },
# '平原':{}
# },
# '青岛':{}
# }
# }
# a=str(menu)
# with open('menu','w',encoding='utf8') as f:
# f.write(a)
#读取menu
with open('menu','r',encoding='utf8') as f:
menu=eval(f.read().strip())
parent_layers=[]
current_layer = menu
while True:
print('欢迎使用省市查询系统'.center(50,'*'))
for key in current_layer:
print('>>>',key)
print('输入你要查询的地区省市或新增[add]、修改[revise]、删除[delete]、返回上一级[q]')
choice = input('>>>').strip()
#查询
if choice in current_layer:
parent_layers.append(current_layer)
current_layer = current_layer[choice]
#新增
elif choice == 'add':
user_add = input('请输入你要添加的省市区:').strip()
if user_add in current_layer:
print('此项已存在,请重新输入')
else:
current_layer[user_add]={}
continue
#修改
elif choice =='revise':
user_revise = input('请输入要修改的省市区:').strip()
if user_revise in current_layer:
user_revise_after = input('修改为:').strip()
current_layer[user_revise_after]=current_layer[user_revise]
del current_layer[user_revise]
continue
#删除
elif choice =='delete':
user_delete = input('请你输入要删除的省市区:').strip()
if user_delete in current_layer:
parent_layers.append(current_layer)
del current_layer[user_delete]
continue
else:
print('此项不存在,请重新输入:')
#返回上一级或退出
elif choice == 'q':
if parent_layers:
current_layer = parent_layers.pop()
else:
print('目前为最上级菜单,输入q后为退出系统!')
print(type(current_layer))
break
else:
print('输入非法,请重新输入选择!')
if type(current_layer) != list:
with open('menu','w',encoding='utf8') as f:
f.write(str(current_layer))
写的很完美,对不对?慢慢来,不急躁。向大神学习。
不过,我个人觉得数据写入这个节点,还是放到代码中间,修改完立即写入比较好。毕竟遇到非正常情况退出,那修改内容就丢失了。另外关于删除城市,有下一级的也全部删除,欠妥,应该提示有子城市,须逐级删。不过真要细化下去,就有得写了。
另外总觉得这节课都是在讲解文本的各种方法,然后布置的这个作业,跟文件的n多方法有多大关联?就一个读一个写?文本处理都没涉及,走歪了也不能全怪我咯
关于字典和文件的章节,暂时告一段落了。