需求:1.不放回抽签 2.把名单上的人员都抽取完以后才能开始下一轮 3.每次打分数都累加 4.可以查看前三和后三名
使用excel实现:思路就是先拿到名单数据,然后抽签(判断抽出来的人在不在新list中),打分,排序。使用递归调用实现多次抽取。
数据样例:
import xlrd import random import sys from openpyxl import load_workbook filename = '参训人员名单.xlsx' name_new_list = [] def open_excel(): xl = xlrd.open_workbook(filename) sheet = xl.sheet_by_index(0) return sheet def read_name(): sheet = open_excel() row_num = sheet.nrows# 获取excel中有多少行 name_score = [] for i in range(1,row_num): value = sheet.row_values(i)#取出每一行的名字和分数 name_score.append(value) new_name_score = dict(name_score) #返回姓名分数列表 return new_name_score def draw_people(): names = read_name() # 获取姓名分数字典 name_list = list(names.keys()) # 把姓名拿出来,当一个列表,用来抽取 if len(name_new_list) == len(name_list):# 如果原始列表和存放抽取名字的列表相等,清空存放名字列表 nu = input('名单上的人员都已被抽过!开启新一轮的抽签请输入1\n 返回上级菜单请输入2\n') if nu == '1': name_new_list.clear() else: return #返回主菜单 people_name = random.choice(name_list) if people_name not in name_new_list: name_new_list.append(people_name) name_num = name_list.index(people_name)+2 # 获取序号+2,因为下标从0开始, print('此次抽中的人员是:',people_name) mark_score(name_num) else: draw_people() def mark_score(people_num): wb = load_workbook(filename) wb1 = wb.active # 激活sheet old_score = wb1.cell(row = people_num,column = 2).value #取出原始分数 print("该人员的现有分数是:",old_score) while True: try: this_score = input("请给抽中的人员打分数(请输入整数):") this_score = int(this_score) break except ValueError: print('请输入一个整数') now_score = int(old_score) + int(this_score) wb1.cell(people_num,2,now_score)#写入分数列 wb.save(filename) # 保存 def sort_score(): #排序 all_score = read_name()#拿到姓名和分数组成的字典 for key in all_score: all_score[key] = int(all_score[key]) # 把数字的小数点去掉才排序 desc = sorted(all_score.items(),key=lambda x:x[1], reverse=False)[:3]#倒序排,输出前三 asc = sorted(all_score.items(),key=lambda x:x[1], reverse=True)[:3]#正序排,输出前三 print("排名前三的人员:",asc) print("排名后三的人员:",desc) def main(): num = input("---抽签,请输入1\n---查看排名,请输入2\n---退出程序,请输入3\n") if num == '1' : draw_people() main() elif num == '2': sort_score() main() else: sys.exit(0) if __name__ == '__main__': main()
用txt实现:先读出全部数据,然后分割成列表。写入的时候现封装成一个列表,再写进去。排序时应该先把value转成int,才能进行排序
数据样例:
import random import sys import codecs import operator filename = '名单.txt' name_new_list = [] name_dict = {} def read_txt(): with codecs.open(filename, 'r', 'utf-8') as fp: data = fp.readlines() ''' 读取到的data: ['张三:62\r\n', '李四:117\r\n', 'waang2:40\r\n', 'yuuu:60\r\n', '李磊:90'] ''' for line in data: name_score = line.replace('\r', '').replace('\n', '').split(':') # 把每一行数据用:拆分成2个元素 ''' ['张三', '62'] ['李四', '117'] ['waang2', '40'] ['yuuu', '60'] ['李磊:90'] ''' if len(name_score) == 2: # 以防txt里面有空行 name_dict[name_score[0]] = int(name_score[1]) #把value转成int,用于后面的加减和排序 return name_dict def draw_people(name_list): if len(name_new_list) == len(name_list): # 如果原始列表和存放抽取名字的列表相等,清空存放名字列表 nu = input('名单上的人员都已被抽过!开启新一轮的抽签请输入1 返回上级菜单请输入2\n') if nu == '1': name_new_list.clear() else: return while True: people_name = random.choice(name_list) if people_name not in name_new_list: name_new_list.append(people_name) print('此次抽中的人员是:', people_name) mark_score(people_name, name_dict) break ''' 使用递归调用 people_name = random.choice(name_list) if people_name not in name_new_list: name_new_list.append(people_name) print('此次抽中的人员是:', people_name) mark_score(people_name, name_dict) else: draw_people() ''' def mark_score(people_name, name_dict): print("该人员的现有分数是:%s分" % (name_dict[people_name])) while True: try: now_score = int(input("请给抽中的人员打分数(请输入整数):")) name_dict[people_name] += now_score # 总分 with open(filename, 'w', encoding='utf-8') as f: tmp = '' for key in name_dict: # 用key来循环,把key和value组装 tmp += (str(key) + ":" + str(name_dict[key]) + '\n') f.writelines(tmp) # 一次性写入 f.close() # 保存 break except ValueError: print('请输入一个整数') def sort_score(name_and_score): # 排序 desc = sorted( name_and_score.items(), key=operator.itemgetter(1), reverse=False)[:3] # 倒序排,输出前三 asc = sorted( name_and_score.items(), key=operator.itemgetter(1), reverse=True)[:3] # 正序排,输出前三 ''' name_and_score.items(): dict_items([('张三', 506), ('李四', '344'), ('waang2', '4029'), ('yuuu', '64')]) operator排序速度比匿名函数更快,也支持多个关键字同时排序。,operator.itemgetter函数获取的不是值,而是定义了一个函数,通过该函数作用到对象上才能获取值。 itemgetter(1)是获取items()对象的第一个域,对域的值排序(对value排序) ''' print("排名前三位的人员:", dict(asc)) print("排名后三位的人员:", dict(desc)) def main(): name_score = read_txt() name_list = list(name_score.keys()) # 把姓名拿出来,当一个列表,用来抽取 num = input("---抽签,请输入1\n---查看排名,请输入2\n---退出程序,请输入3\n请输入:") if num == '1': draw_people(name_list) print('\r') main() elif num == '2': sort_score(name_score) print('\r') main() else: sys.exit(0) if __name__ == '__main__': main()
抽签方法不用递归,用while循环实现
def draw_people(): name_score = read_txt() name_list = list(name_score.keys()) # 把姓名拿出来,当一个列表,用来抽取 if len(name_new_list) == len(name_list):# 如果原始列表和存放抽取名字的列表相等,清空存放名字列表 nu = input('名单上的人员都已被抽过!开启新一轮的抽签请输入1 返回上级菜单请输入2\n') if nu == '1': name_new_list.clear() else: return while True: people_name = random.choice(name_list) if people_name not in name_new_list: name_new_list.append(people_name) print('此次抽中的人员是:',people_name) mark_score(people_name,name_dict) break