问题描述

作为一个学委,通常的任务就是收取班级作业,然后向老师报告当前未交人员的名单

JS版本:实现以一个表格数据查询另一个表格【JS】

之前我已经尝试通过用JS实现了,本质上差别其实也不是很大,只是对于JS来说,文件处理是它的硬伤之一,因为他设计之初就不是为了文本处理,而且你要想,如果js能随意获取你计算机上的文件,那会不会有些惊悚了(当然可以通过node中的fs模块实现,但终究有点小问题)

因此,为针对文件处理这一类的问题,我就尝试使用python去解决了

需求描述

  • 获取当前已提交文件的所有人
  • 获取班级名单Excel
  • 查询未提交的人数

实现代码

import os
import xlrd
import re
turnInPath = input('已上交的文件目录:')
classListPath = "D://Leo//Document//Class//xxxxxx.xlsx"
# os.listdir:参数为文件夹路径,可以返回文件夹下的所有子文件夹、文件名称
# 不能返回子文件夹下的文件
fileArr = os.listdir(turnInPath)
fileStr = "|".join(fileArr)

worksheet = xlrd.open_workbook(classListPath)
sheet_names= worksheet.sheet_names()
for sheet_name in sheet_names:
    sheet = worksheet.sheet_by_name(sheet_name)
    cols = sheet.col_values(1) # 获取第二列内容, 数据格式为此数据的原有格式(原:字符串,读取:字符串;  原:浮点数, 读取:浮点数)
    del cols[0] # 删除第一位的列名
    classList = cols


isChinese = re.compile(u'[\u4e00-\u9fa5]') #中文的范围为\u4e00-\u9fa5
turnInList = []
for fileName in fileArr:
    arr = isChinese.findall(fileName)
    turnInList.append(''.join(arr))

# 在提交列表 & 在班级列表 (为了处理非本班的提交)
# 若能完全确定一定是本班的,则为了效率可注释
# 该段代码通常适用于 两个班混交 or 统一分组(不过这个需要读取Excel了)
# diff = [ ]
# for item in turnInList: 
#     if(item in classList):
#         diff.append(item) 

# 在班级列表 && 不在(真实上交列表)
for item in classList:
    if(item not in "".join(turnInList)):
        print(item)

代码解释

获取已提交人员信息

输入路径

为方便多次复用,这里特地将文件目录进行输入,并进行适当提示

turnInPath = input('已上交的文件目录:')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sAwNDvTI-1670687485616)(assets/image-20221210234232-erxlaeu.png)]

读取文件夹

通过使用python内置模块os,获取所有文件名称

# os.listdir:参数为文件夹路径,可以返回文件夹下的所有子文件夹、文件名称
# 不能返回子文件夹下的文件
fileArr = os.listdir(turnInPath)

读取中文

从所有提交名单中获取中文(中文名称大概率就是姓名了,当然可能存在作业等冗余后缀,这些后面会处理)

  • 设置正则
  • 循环处理

isChinese = re.compile(u'[\u4e00-\u9fa5]') #中文的范围为\u4e00-\u9fa5
turnInList = []
for fileName in fileArr:
    arr = isChinese.findall(fileName)
    turnInList.append(''.join(arr))

首先对os.listdir进行循环,获取所有文件名中为中文的,放入turnInlist数组中

获取班级名单

设置班级名单路径

因为这里班级名单基本不变,因此就直接定为常量了

classListPath = "D://Leo//Document//Class//xxxxx.xlsx"

打开花名册

worksheet = xlrd.open_workbook(classListPath)

获取列

sheet_names= worksheet.sheet_names()
for sheet_name in sheet_names:
    sheet = worksheet.sheet_by_name(sheet_name)

获取列

 sheet = worksheet.sheet_by_name(sheet_name)
    cols = sheet.col_values(1) # 获取第二列内容, 数据格式为此数据的原有格式(原:字符串,读取:字符串;  原:浮点数, 读取:浮点数)
    del cols[0] # 删除第一位的列名
    classList = cols

这里解释一下为什么要杀出数组的第一个

因为通常情况下,我们的班级名单中的列通常会是这样的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6MJ4NkgS-1670687485617)(assets/image-20221210234928-g27cfah.png)]

这样就会多余出一行来

输出未提交名单

# 在班级列表 && 不在(真实上交列表)
for item in classList:
    if(item not in "".join(turnInList)):
        print(item)

这里只需要注意一点的就是"".join(turnInList),为什么这里需要转为字符串?

因为这里我们需要做到的是最大匹配

也就是说,如果有一个提交的命名为张三的作业.xxx的话,通过判断是否是classList中的元素是否是turnInList的子串即可实现对张三的判断

当然这可能存在一个问题:如果某个同学的文件命名为张三-李四.xxx,而李四又没有上交作业,在这段代码中就会判断李四也上交了作业
但是,这种情况在日常的作业收集中出现概率较小,因此不予考虑

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐