鱼C论坛

 找回密码
 立即注册
查看: 2807|回复: 13

[已解决]实在无法理解这一块代码

[复制链接]
发表于 2023-1-2 02:04:56 | 显示全部楼层 |阅读模式
5鱼币

本题 包含文件附件,请有空的高手帮助以下,这题因为真的卡了三天,实在走投无路,自己也解读了答案中99%的代码,只剩下一条无法理解


要求根据id.txt和finalscore.txt生成学生成绩。文件都是utf-8格式的

1) id.txt 里面放着学号和姓名,没有排序。姓名很怪,不要在乎
2) finalscore.txt里面放着学生的做题信息。其中第三栏或第四栏是做题数量
   有的学生昵称是学号,有的是姓名,有的是姓名学号都有。只要有学号或姓名,就有效
3) 分数计算办法: 1题50,2题60,此后每做一题加4分
4) 生成id.txt里面有的所有学生的成绩,按学号排序输出到指定的结果文件。
如果在 finalscore里面找不到学生的做题记录,该生题数和成绩都记0

结果文件格式如:

学号        姓名        题数        分数
1700943357        玘尜寋        0        0
1700943359        杛旺煃        0        0
1700943383        玘签翢        2        60
1700943405        陕榄伳        0        0
1700943465        匒乡奡        5        72
1700943469        巸俗杽        3        64
1700943472        钬内佦        0        0
1700943481        別珜辽        0        0
1700943523        趂盨淦        7        80


这样的结果可以导入excel表格(拷贝粘贴即可)

id.txt里面没有的学生,不用处理。

注意:源文件和目标文件里面的分隔符,都不是空格,都是制表符 \t (Tab)
注意看finalscore.txt里面,有连着两个 Tab 的情况,比如下面学号和做题数之间是2个tab:


4        1700943836                9


也许你需要关注这一点,也许并不需要

5)程序文件名必须叫count.py。运行时,将count.py和id.txt, finalscore.txt放在相同文件夹下面,
然后在命令行窗口进入该文件夹,以命令行方式运行程序,命令行中可以指定结果文件名:

python count.py XXX.txt 

程序在同一个文件夹下生成结果文件XXX.txt。这个文件名可以随便指定

6)正确的结果已经给出,即ans.txt。最终生成的结果应该和ans.txt文件一致


以下是网上搜索到的答案
import re
import sys
def chazhao(x,y):
    l=len(y)
    for i in range(l):
        if x in y[i]:
            return i
    return -1

def grade(a):
    if a==1:
        x=50
    elif a==2:
        x=60
    elif a>2:
        x=60+(a-2)*4
    else:
        x=0
    return x

f=open('id.txt','r',encoding='utf-8')
students=f.readlines()
f.close()
students.sort()

f=open('finalscore.txt','r',encoding='utf-8')
score=f.readlines()
f.close()

f=open(sys.argv[1],'w',encoding='utf-8')
f.write("学号\t姓名\t题数\t分数\n")

for x in students:
    l=x.split()
    x1,x2=l[0],l[1]
    if chazhao(x1,score)!=-1 or chazhao(x2,score)!=-1:
        i=chazhao(x1,score)
        if i==-1:
            i=chazhao(x2,score)
        l1=re.split('\t',score[i])
        a=int(l1[3])
        agrade=grade(a)
        f.write("%s\t%s\t%d\t%d\n"%(x1,x2,a,agrade))
    else:
        f.write("%s\t%s\t%d\t%d\n"%(x1,x2,0,0))
f.close()


答案中第40行代码我无法理解
        l1=re.split('\t',score[i])

这行代码的i,我无法理解,因为上面 chazhao(x,y)中必然是产生1或者-1,他不是一个循环

而l1=re.split('\t',score[i]) 中我理解是这个i需要一个循环才能每次轮换内容,如果一直都是1那永远都是第一行



而这题我对题目的理解解决思路是这样的,希望有错能更正一下

目标按照文件ID里面的数据作为索引,在文件finalscore寻找数据补充回ID文件

因为finalscore文件内容有错乱内容,我一开始打算先整理好finalscore文件内容再提取,这样感觉简单,但最后连整理也花了半天也没整理出来

然后最后按照上面代码思路,以ID文件作为索引,校验finalscore内容,存在则提取不存在则跳过,然后就卡在了我上面的那个代码那里,因为我写不出,就去搜答案,发现这个答案跟我的思路基本一样,但我看不懂40行这段

还有其他解题思路可以提供下吗?
最佳答案
2023-1-2 02:04:57
def chazhao(x,y):
    l=len(y)
    for i in range(l):
        if x in y[i]:
            return i
    return -1
找到了返回的是 字母i  不是数字1,你看错了

        i=chazhao(x1,score)
        if i==-1:
            i=chazhao(x2,score)
这几行代码的意思是,id.txt里的学生若找到了
如果是找到学号了,那么chazhao(x1,score)肯定是返回第几行。但是如果chazhao(x1,score)返回-1则说明不是按照学号找到的,那么就是按照名字找到的,这时候
i=chazhao(x2,score) 这句代码就是按照名字找,看看在第几行,并赋值给 i

然后下边那句话l1=re.split('\t',score) 是把找到的这一行,按照‘\t’切割,切割出来几项。其中第三项或者第四项就是这个人的答题数
下边这句话a=int(l1[3])是个bug,因为分数不一定在第四项,(其中第三栏或第四栏是做题数量)这句话有可能报错。
我的想法是
try:
    a=int(l1[2])
except:
    a=int(l1[3])

但是我并没有跑一遍代码,不知道改的对不对,如果改的对了你也理解了麻烦给我最佳
如果还有哪里没看懂也欢迎继续问

文件处理作业.zip

10.98 KB, 下载次数: 3

最佳答案

查看完整内容

找到了返回的是 字母i 不是数字1,你看错了 i=chazhao(x1,score) if i==-1: i=chazhao(x2,score) 这几行代码的意思是,id.txt里的学生若找到了 如果是找到学号了,那么chazhao(x1,score)肯定是返回第几行。但是如果chazhao(x1,score)返回-1则说明不是按照学号找到的,那么就是按照名字找到的,这时候 i=chazhao(x2,score) 这句代码就是按照名字找,看看在第几行,并赋值给 i 然后下边那 ...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-1-2 02:04:57 | 显示全部楼层    本楼为最佳答案   
def chazhao(x,y):
    l=len(y)
    for i in range(l):
        if x in y[i]:
            return i
    return -1
找到了返回的是 字母i  不是数字1,你看错了

        i=chazhao(x1,score)
        if i==-1:
            i=chazhao(x2,score)
这几行代码的意思是,id.txt里的学生若找到了
如果是找到学号了,那么chazhao(x1,score)肯定是返回第几行。但是如果chazhao(x1,score)返回-1则说明不是按照学号找到的,那么就是按照名字找到的,这时候
i=chazhao(x2,score) 这句代码就是按照名字找,看看在第几行,并赋值给 i

然后下边那句话l1=re.split('\t',score) 是把找到的这一行,按照‘\t’切割,切割出来几项。其中第三项或者第四项就是这个人的答题数
下边这句话a=int(l1[3])是个bug,因为分数不一定在第四项,(其中第三栏或第四栏是做题数量)这句话有可能报错。
我的想法是
try:
    a=int(l1[2])
except:
    a=int(l1[3])

但是我并没有跑一遍代码,不知道改的对不对,如果改的对了你也理解了麻烦给我最佳
如果还有哪里没看懂也欢迎继续问
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-1-2 08:35:18 | 显示全部楼层
研究一下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-1-2 11:16:04 | 显示全部楼层

老哥你的回复实在太水了
看了一下你的其他回复
更水了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-1-2 11:20:30 | 显示全部楼层
jcpython2 发表于 2023-1-2 11:16
老哥你的回复实在太水了
看了一下你的其他回复
更水了

额,我已经很不睡了,至少还打点字,别人都一个表情
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-1-2 13:37:35 | 显示全部楼层
本帖最后由 阿奇_o 于 2023-1-2 13:41 编辑

难点一:finalscore.txt里的记录 存在 名字和学号混连在一起的情况,我尝试用正则表达式一次获取,发现过于复杂,只能退一步,分情况来获取到需要的 (学号, 姓名, 题数)。
难点二:提取到了这些名字或学号,再到ids.txt里,根据名字找学号,或根据学号找名字。。 还要补全没有在finalscore.txt里的学生(缺考0题目数)。。 最后根据题数计算分数。
难点三:很多关于字符串操控和列表遍历的各种小细节
import sys, re

def get_scores(file):
    with open(file, 'r', encoding='utf8') as f:
        lines = f.readlines()     
        stu_only_name = list(map(lambda x: re.findall('^(\d+)[\t ]([\u4e00-\u9fa5]{1,})[\t ]+(\d+)', x), lines))    
        print(stu_only_name)

        stu_with_id = list(map(lambda x: re.findall('(\d+)[\t ]+(\d{10})[\t ]+(\d+?)[\t ]+\d+:', x), lines))
        print(stu_with_id)

        with open('id.txt', 'r', encoding='utf8') as f2:
            id_name = dict(map(str.split, f2.readlines()))
            name_id = dict(zip(id_name.values(), id_name.keys()))
            print(name_id)
            fixed_id = {i[0][1]: name_id.get(i[0][1]) for i in stu_only_name 
                            if i and len(i[0]) == 3 and i[0][1] in name_id }
            print('\nfixed_id: ', fixed_id)
        
            tmp = [ [i[0][0]] + [fixed_id.get(i[0][1])] + list(i[0][1:]) for i in stu_only_name 
                        if i and i[0][1] in name_id]
            print(tmp)

            s2 = [list(i[0][:2]) + [id_name.get(i[0][1]), i[0][2]] for i in stu_with_id 
                        if i and i[0][1] in id_name]
            print(s2)

        scores = []
        s2.extend(tmp)
        for i in s2:
            if i:
                r, t = list(i)[1:3], i[3]
                if t ==   '0':
                    scores.append(r + [t, '0'])   
                elif t == '1':
                    scores.append(r + [t, '50'])
                elif t == '2':
                    scores.append(r + [t, '60'])
                else:
                    scores.append(r + [t, str(60 + (int(t)-2)*4) ])
        for id in id_name.keys():
            if id not in [i[0] for i in scores]:
                scores.append([id, id_name[id], '0', '0'])
                
        # print(sorted(scores, key=lambda x: x[0])) 
        return sorted(scores, key=lambda x: x[0])

def save_ans(scores, file='my_ans.txt'):
    with open(file, 'w', encoding='utf8', newline='\n') as f:
        f.write('\t'.join(['学号','姓名','题数','分数']))
        f.write('\n')
        for s in sorted(scores, key=lambda x:x[0]):
            f.write('\t'.join(s))
            f.write('\n')

            

if __name__ == '__main__': 
    file = sys.argv[1]
    # print(file)
    scores = get_scores(file) 
    save_ans(scores, file='my_ans.txt')
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-1-2 15:03:42 | 显示全部楼层
楼主的百度的程序,直接生成标准答案,没有错误。
首行要加:
#coding=gbk
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-1-2 15:16:26 | 显示全部楼层
#coding=gbk
import re
import sys
def chazhao(x,y):
    l=len(y)
    for i in range(l):
        if x in y[i]:
            return i
    return -1

def grade(a):
    if a==1:
        x=50
    elif a==2:
        x=60
    elif a>2:
        x=60+(a-2)*4
    else:
        x=0
    return x

f=open('id.txt','r',encoding='utf-8')
students=f.readlines()
f.close()
students.sort()

f=open('finalscore.txt','r',encoding='utf-8')
score=f.readlines()
f.close()
print("为便于测试,文本文件暂时设中12345.text,当前工作路径:",sys.argv[0])
f=open("12345.text",'w',encoding='utf-8')
f.write("学号\t姓名\t题数\t分数\n")
for x in students:
    l=x.split()
    x1,x2=l[0],l[1]
    if chazhao(x1,score)!=-1 or chazhao(x2,score)!=-1:
        i=chazhao(x1,score)
        if i==-1:
            i=chazhao(x2,score)
        l1=re.split('\t',score[i])
        a=int(l1[3])
        agrade=grade(a)
        f.write("%s\t%s\t%d\t%d\n"%(x1,x2,a,agrade))
    else:
        f.write("%s\t%s\t%d\t%d\n"%(x1,x2,0,0))
f.close()
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-1-2 16:28:49 | 显示全部楼层
洋洋痒 发表于 2023-1-2 07:19
找到了返回的是 字母i  不是数字1,你看错了

        i=chazhao(x1,score)
def chazhao(x,y):
    l=len(y)
    for i in range(l):
        if x in y[i]:
            return i
    return -1

但是i=chazhao(x2,score)按照上面函数的结果是永远都只会是得到1或者-1呢,所以我疑惑这点.这函数决定了他永远只能1或者-1吧??
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-1-2 16:30:01 | 显示全部楼层
洋洋痒 发表于 2023-1-2 07:19
找到了返回的是 字母i  不是数字1,你看错了

        i=chazhao(x1,score)

晕死,我终于看清了

return i

不是return 1

晕死了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-1-2 17:41:44 From FishC Mobile | 显示全部楼层
jcpython2 发表于 2023-1-2 16:30
晕死,我终于看清了

return i

你都没有仔细看我的回答啊,我写的清清楚楚是字母i了啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-1-2 18:29:15 | 显示全部楼层
洋洋痒 发表于 2023-1-2 17:41
你都没有仔细看我的回答啊,我写的清清楚楚是字母i了啊

有的,我有看你的代码的,主要是我一开始去读答案的时候把def chazhao的返回误会成1or-1,看你答案一边醒一边回,我还在消化中,再次感谢老哥
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-1-2 21:46:26 | 显示全部楼层
改进版本2:先从id.txt里找学号和学生姓名,再根据学号或姓名到finalscore.txt里找题数,并计算分数。。  
这样清晰多了。。我前一个版本是反过来找,搞复杂了。。
import sys, re

def main(file):
    with open(file, 'r', encoding='utf8') as f:
        t_lines = f.readlines()

    with open('id.txt', 'r', encoding='utf8') as f2:
        id_name = list(map(lambda x: x.strip().split('\t'), f2.readlines()))
        # print(id_name)
        scores = dict()  # 用字典,方便后面去重和查找
        for id, name in id_name:
            for line in t_lines:
                if id in line or name in line:
                    m = re.match('(\d+)[\t ].*?(\d+?)[\t ]+\d+:', line)  # 匹配序号和题数
                    if m:
                        t = m.group(2)  # 只取"题数"
                        # print(t.group(1), id, name, t)  # 打印检查是否正确
                        if t == '0':
                            scores[id] = [id, name, t, '0']
                        elif t == '1':
                            scores[id] = [id, name, t, '50']
                        elif t == '2':
                            scores[id] = [id, name, t, '60']
                        else:
                            scores[id] = [id, name, t, str(60 + (int(t)-2)*4) ]
  
        for id, name in id_name:
            scores.setdefault(id, [id, name, '0', '0'])   # 补上 缺考学生的成绩
    
    # for s in sorted(scores.values(), key=lambda x: x[0]):  # 因学号就位于第一个位置,这里key对比函数可省略
    #     print(s)
    with open('my_ans2.txt', 'w', encoding='utf8', newline='\n') as f:
        f.write('\t'.join(['学号','姓名','题数','分数']))
        f.write('\n')
        for s in sorted(scores.values()): 
            f.write('\t'.join(s))
            f.write('\n')
          
if __name__ == '__main__': 
    file = sys.argv[1]
    main(file)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-1-3 15:18:49 | 显示全部楼层
楼上正解
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-25 03:28

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表