python-实现不放回抽签

需求: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
 返回上级菜单请输入2
')
        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
---查看排名,请输入2
---退出程序,请输入3
")
    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
', '李四:117
', 'waang2:40
', 'yuuu:60
', '李磊:90']
        '''
        for line in data:
            name_score = line.replace('
', '').replace('
', '').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
')
        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]) + '
')
                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
---查看排名,请输入2
---退出程序,请输入3
请输入:")
    if num == '1':
        draw_people(name_list)
        print('
')
        main()
    elif num == '2':
        sort_score(name_score)
        print('
')
        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
')
        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
原文地址:https://www.cnblogs.com/dydxw/p/14973053.html