鱼C论坛

 找回密码
 立即注册
查看: 1019|回复: 9

[已解决]第30讲 第4题 查找关键字的具体位置 为啥我的程序跑不对啊

[复制链接]
发表于 2020-4-22 17:36:32 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x

代码思路我都写在注释里了,为什么跑不出来啊,请各位帮忙看看吧!谢谢大家

主要思路就是:一个文件有关键字,这个文件创一个列表each_txt,列表里放字典line_site,字典的键是行数line_num,值是列数site_num(字符位置)且值site_num也是一个列表(因为有多个位置)

  1. import os

  2. paths = []       # 存放有关键字的文件的路径
  3. each_txt = []    # 存放每个文件中每个关键字{行:列}字典的列表

  4. def search_keyword(keyword) :   
  5.     all_files = os.listdir(os.curdir)
  6.    
  7.     for each_file in all_files:
  8.         ext = os.path.splitext(each_file)[1]
  9.         
  10.         if os.path.isdir(each_file) :
  11.             os.chdir(each_file)
  12.             search_keyword(keyword)   
  13.             os.chdir(os.pardir)  
  14.             
  15.         if ext == '.txt':
  16.             path = os.getcwd() + os.sep + each_file   # path保存文本文件路径
  17.             f = open(each_file)
  18.             line_site = dict()   # 存放每个关键字{行:列}的字典,每个新文件都要置空
  19.             line_num = 0  
  20.             
  21.             for each_line in f:
  22.                 site_num = []    # 存放【列】的列表,每一行查找时都要置空
  23.                 line_num += 1    # 每行的行数每次 +1
  24.                
  25.                 while 1:
  26.                     i = 0
  27.                     site = each_line.find(keyword, i)   # 查找关键字,如果有返回关键字的第一个索引号(即列),没有返回-1
  28.                     if site != -1:             # 查到关键字
  29.                         site_num.append(site)  # 将关键字的第一个索引号即列值加入列表中
  30.                         i = site + 1           # 从site后一个位置查找这一行还有没有关键字(11在1111中的数目
  31.                     else:                      # 如果没有找到关键字
  32.                         break                  # 说明each_line这一行检索完毕或根本没有关键字,退出while循环查找下一行
  33.                         
  34.                 if site_num == []:                  # 如果【列】的列表是空的,说明这一行没有关键字
  35.                     continue                        # 继续查找下一行
  36.                 else:                               # 如果【列】的列表不是空的,说明这一行有关键字
  37.                     line_site[line_num] = site_num  # 在字典中添加{行数(数字):列数【列表】}
  38.                     each_txt.append(line_site)      # 在这个文件的列表中添加字典
  39.                     
  40.             if line_site == {}:      # 如果字典是空的,说明没有{行:列}添加,即此文件中没有关键字
  41.                 continue             # 退出查找每行的for循环,查找下一文件
  42.             else:                    # 如果字典不是空的,说明有{行:列}添加,即此文件中有关键字
  43.                 paths.append(path)   # 添加此文件的路径
  44.                
  45.             f.close()
  46.             
  47. keyword = input('请将该脚本放于待查找的文件夹内,请输入关键字:')
  48. search_keyword(keyword)      
  49. decide = input('请问是否需要打印关键字【%s】在文件中大的具体位置(YES/NO):' % keyword)

  50. if decide in ['YES', 'yes', 'Yes']:
  51.    
  52.     if paths == []:    # 为空说明没有存在关键字的文件
  53.         print('===================================================')
  54.         print('当前文件夹内所有文本文件均不含有此关键字!')
  55.     else:
  56.         print('===================================================')
  57.         
  58.         for each_path in paths:    # paths有一个元素就说明有一个文件有关键字
  59.             print('在文件【%s】中找到关键字【%s】' % (each_path, keyword))            
  60.             
  61.             for each_line_site in each_txt:    # each_txt是一个列表(每个文件一个列表),每个元素each_line_site都为字典
  62.                
  63.                 for each_item in each_line_site.items():    # each_item是字典的每一项,是一个元组(键(行),值(列))
  64.                     print('关键字出现在第 %d 行,第' % each_item(0), each_item(1), '个位置。')  # 值(列)是一个列表
复制代码
最佳答案
2020-4-24 01:56:01
本帖最后由 txxcat 于 2020-4-24 01:58 编辑
yangxuebabe 发表于 2020-4-23 22:00
您好 我按照您说的修改了
但是结果还是有点问题


你的代码还有几处错误,看注释:
  1. import os

  2. paths = []       # 存放有关键字的文件的路径
  3. each_txt = []    # 存放每个文件中每个关键字{行:列}字典的列表

  4. def copen(filename):
  5.     try:
  6.         f = open(filename,encoding='GBK')
  7.         try:
  8.             f.read()
  9.             f.seek(0)
  10.         except UnicodeDecodeError:
  11.             f = open(filename,encoding='utf-8',errors='ignore')
  12.     except (OSError,AttributeError) as reason:
  13.         print(str(reason))
  14.         return None
  15.     return f

  16. def search_keyword(keyword) :   
  17.     all_files = os.listdir(os.curdir)
  18.    
  19.     for each_file in all_files:
  20.         ext = os.path.splitext(each_file)[1]
  21.         
  22.         if os.path.isdir(each_file) :
  23.             os.chdir(each_file)
  24.             search_keyword(keyword)   
  25.             os.chdir(os.pardir)  
  26.             
  27.         if ext == '.txt':
  28.             path = os.getcwd() + os.sep + each_file
  29.             f = copen(each_file)      #用函数copen打开防止编码错误
  30.             line_site = dict()
  31.             line_num = 0  
  32.             
  33.             for each_line in f:
  34.                 site_num = []
  35.                 line_num += 1
  36.                
  37.                 i = 0
  38.                 while 1:
  39.                     site = each_line.find(keyword, i)
  40.                     if site != -1:
  41.                         site_num.append(site+1)            #python索引从0开始,人类习惯1开始
  42.                         i = site + 1
  43.                     else:
  44.                         break
  45.                         
  46.                 if site_num == []:
  47.                     continue
  48.                 else:
  49.                     line_site[line_num] = site_num
  50. #                    each_txt.append(line_site)          #在这里append,每找到一行就append一次,重复数据导致错误
  51.                     
  52.             if line_site == {}:
  53.                 continue
  54.             else:
  55.                 paths.append(path)
  56.                 each_txt.append(line_site)               #在这里append就不会有重复数据
  57.             f.close()

  58. keyword = input('请将该脚本放于待查找的文件夹内,请输入关键字:')
  59. search_keyword(keyword)      
  60. decide = input('请问是否需要打印关键字【%s】在文件中大的具体位置(YES/NO):' % keyword)

  61. if decide.strip().lower()=='yes':              #这样可以对付任意大小写组合,还有空格
  62.    
  63.     if paths == []:
  64.         print('===================================================')
  65.         print('当前文件夹内所有文本文件均不含有此关键字!')
  66.     else:
  67.         print('===================================================')
  68.         for i in range(len(paths)):                                       #原有的代码是有多少符合条件的文件,就把所有的答案重复打印多少次
  69.             print('在文件【%s】中找到关键字【%s】' % (paths[i], keyword))   #只打印和文件对应的字典
  70.             for j,k in each_txt[i].items():
  71.                 print('关键字出现在第 %d 行,第%s个位置。' % (j, k))
  72.                
  73. #         for each_path in paths:    # paths有一个元素就说明有一个文件有关键字
  74. #             print('在文件【%s】中找到关键字【%s】' % (each_path, keyword))            
  75. #            
  76. #             for each_line_site in each_txt:    # each_txt是一个列表(每个文件一个列表),每个元素each_line_site都为字典
  77. #                 
  78. #                 for each_item in each_line_site.items():    # each_item是字典的每一项,是一个元组(键(行),值(列))
  79. #                     print('关键字出现在第 %d 行,第' % each_item[0], each_item[1], '个位置。')  # 值(列)是一个列表
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-4-22 18:52:38 | 显示全部楼层
这是个死循环:
  1.                 while 1:
  2.                     i = 0
  3.                     site = each_line.find(keyword, i)   # 查找关键字,如果有返回关键字的第一个索引号(即列),没有返回-1
  4.                     if site != -1:             # 查到关键字
  5.                         site_num.append(site)  # 将关键字的第一个索引号即列值加入列表中
  6.                         i = site + 1           # 从site后一个位置查找这一行还有没有关键字(11在1111中的数目
  7.                     else:                      # 如果没有找到关键字
  8.                         break                  # 说明each_line这一行检索完毕或根本没有关键字,退出while循环查找下一行
复制代码

i每次循环都初始化为0,所以只要包含关键字,就成了死循环,把i=0放在外面就可以了:
  1.                 i = 0
  2.                 while 1:
  3.                      site = each_line.find(keyword, i)   # 查找关键字,如果有返回关键字的第一个索引号(即列),没有返回-1
  4.                     if site != -1:             # 查到关键字
  5.                         site_num.append(site)  # 将关键字的第一个索引号即列值加入列表中
  6.                         i = site + 1           # 从site后一个位置查找这一行还有没有关键字(11在1111中的数目
  7.                     else:                      # 如果没有找到关键字
  8.                         break                  # 说明each_line这一行检索完毕或根本没有关键字,退出while循环查找下一行
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-22 18:59:06 | 显示全部楼层
顺便说一下,测试的时候碰到编码错,批量处理文本文件的时候难免碰到编码不同的文件,可以参考这个帖子改一下代码:避免打开文本文件出现编码错误的一个小技巧
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-4-23 22:00:29 | 显示全部楼层
txxcat 发表于 2020-4-22 18:52
这是个死循环:

i每次循环都初始化为0,所以只要包含关键字,就成了死循环,把i=0放在外面就可以了:

您好 我按照您说的修改了
但是结果还是有点问题

运行结果是:

请将该脚本放于待查找的文件夹内,请输入关键字:of
请问是否需要打印关键字【of】在文件中大的具体位置(YES/NO):yes
===================================================
在文件【F:\Python\JupyterProject\猪猪大数据\city.txt】中找到关键字【of】
关键字出现在第 3 行,第 [54, 93] 个位置。
关键字出现在第 7 行,第 [27, 106, 311, 401] 个位置。
关键字出现在第 3 行,第 [54, 93] 个位置。
关键字出现在第 7 行,第 [27, 106, 311, 401] 个位置。
关键字出现在第 17 行,第 [0] 个位置。
===================================================
在文件【F:\Python\JupyterProject\面朝大海,春暖花开.txt】中找到关键字【of】
关键字出现在第 3 行,第 [54, 93] 个位置。
关键字出现在第 7 行,第 [27, 106, 311, 401] 个位置。
关键字出现在第 3 行,第 [54, 93] 个位置。
关键字出现在第 7 行,第 [27, 106, 311, 401] 个位置。
关键字出现在第 17 行,第 [0] 个位置。

第3行和第7行是第一个文件的,打印了两次
第17行是第二个文件的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-24 01:56:01 | 显示全部楼层    本楼为最佳答案   
本帖最后由 txxcat 于 2020-4-24 01:58 编辑
yangxuebabe 发表于 2020-4-23 22:00
您好 我按照您说的修改了
但是结果还是有点问题


你的代码还有几处错误,看注释:
  1. import os

  2. paths = []       # 存放有关键字的文件的路径
  3. each_txt = []    # 存放每个文件中每个关键字{行:列}字典的列表

  4. def copen(filename):
  5.     try:
  6.         f = open(filename,encoding='GBK')
  7.         try:
  8.             f.read()
  9.             f.seek(0)
  10.         except UnicodeDecodeError:
  11.             f = open(filename,encoding='utf-8',errors='ignore')
  12.     except (OSError,AttributeError) as reason:
  13.         print(str(reason))
  14.         return None
  15.     return f

  16. def search_keyword(keyword) :   
  17.     all_files = os.listdir(os.curdir)
  18.    
  19.     for each_file in all_files:
  20.         ext = os.path.splitext(each_file)[1]
  21.         
  22.         if os.path.isdir(each_file) :
  23.             os.chdir(each_file)
  24.             search_keyword(keyword)   
  25.             os.chdir(os.pardir)  
  26.             
  27.         if ext == '.txt':
  28.             path = os.getcwd() + os.sep + each_file
  29.             f = copen(each_file)      #用函数copen打开防止编码错误
  30.             line_site = dict()
  31.             line_num = 0  
  32.             
  33.             for each_line in f:
  34.                 site_num = []
  35.                 line_num += 1
  36.                
  37.                 i = 0
  38.                 while 1:
  39.                     site = each_line.find(keyword, i)
  40.                     if site != -1:
  41.                         site_num.append(site+1)            #python索引从0开始,人类习惯1开始
  42.                         i = site + 1
  43.                     else:
  44.                         break
  45.                         
  46.                 if site_num == []:
  47.                     continue
  48.                 else:
  49.                     line_site[line_num] = site_num
  50. #                    each_txt.append(line_site)          #在这里append,每找到一行就append一次,重复数据导致错误
  51.                     
  52.             if line_site == {}:
  53.                 continue
  54.             else:
  55.                 paths.append(path)
  56.                 each_txt.append(line_site)               #在这里append就不会有重复数据
  57.             f.close()

  58. keyword = input('请将该脚本放于待查找的文件夹内,请输入关键字:')
  59. search_keyword(keyword)      
  60. decide = input('请问是否需要打印关键字【%s】在文件中大的具体位置(YES/NO):' % keyword)

  61. if decide.strip().lower()=='yes':              #这样可以对付任意大小写组合,还有空格
  62.    
  63.     if paths == []:
  64.         print('===================================================')
  65.         print('当前文件夹内所有文本文件均不含有此关键字!')
  66.     else:
  67.         print('===================================================')
  68.         for i in range(len(paths)):                                       #原有的代码是有多少符合条件的文件,就把所有的答案重复打印多少次
  69.             print('在文件【%s】中找到关键字【%s】' % (paths[i], keyword))   #只打印和文件对应的字典
  70.             for j,k in each_txt[i].items():
  71.                 print('关键字出现在第 %d 行,第%s个位置。' % (j, k))
  72.                
  73. #         for each_path in paths:    # paths有一个元素就说明有一个文件有关键字
  74. #             print('在文件【%s】中找到关键字【%s】' % (each_path, keyword))            
  75. #            
  76. #             for each_line_site in each_txt:    # each_txt是一个列表(每个文件一个列表),每个元素each_line_site都为字典
  77. #                 
  78. #                 for each_item in each_line_site.items():    # each_item是字典的每一项,是一个元组(键(行),值(列))
  79. #                     print('关键字出现在第 %d 行,第' % each_item[0], each_item[1], '个位置。')  # 值(列)是一个列表
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-4-24 09:41:45 | 显示全部楼层
txxcat 发表于 2020-4-24 01:56
你的代码还有几处错误,看注释:

天哪太感谢了!!好细心!!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-4-24 11:51:48 | 显示全部楼层
txxcat 发表于 2020-4-24 01:56
你的代码还有几处错误,看注释:

大神 还有一个问题,就是,如果按照我原来的代码,append会导致数据重复,我的想法重复的结果应该是:

比如在第一行的第1个字符找到关键字
那么append一个字典  [{1:1}]

然后在第二行的第2个字符找到关键字
此时字典更新为{1:1, 2:2},再次append这个字典,那此时的列表each_txt应为 [{1:1}, {1:1, 2:2}]

可是为什么程序显示的是  [{1:1, 2:2}, {1:1, 2:2}]
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-4-24 13:49:00 | 显示全部楼层
txxcat 发表于 2020-4-24 01:56
你的代码还有几处错误,看注释:

还有一个问题。。我看了标准答案,用了sort()对字典进行排序,但是为什么我的程序没有进行排序也是自动按顺序打印的?我试了好几个关键字好多次都是按照行数顺序打印的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-24 19:09:24 | 显示全部楼层
yangxuebabe 发表于 2020-4-24 11:51
大神 还有一个问题,就是,如果按照我原来的代码,append会导致数据重复,我的想法重复的结果应该是:

...

因为append的是字典变量名而不是字典的值,做个实验:
  1. >>> a={}
  2. >>> a['1']=1
  3. >>> b=[]
  4. >>> b.append(a)
  5. >>> b
  6. [{'1': 1}]
  7. >>> a['2']=2
  8. >>> a
  9. {'1': 1, '2': 2}
  10. >>> b.append(a)
  11. >>> b
  12. [{'1': 1, '2': 2}, {'1': 1, '2': 2}]
复制代码

能看明白吧?不是字典如此,列表加入列表也是如此。
为什么用sorted,个人感觉没必要,因为正常情况下字典就是按行号顺序生成的。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-4-24 19:39:35 | 显示全部楼层
txxcat 发表于 2020-4-24 19:09
因为append的是字典变量名而不是字典的值,做个实验:

能看明白吧?不是字典如此,列表加入列表也是如 ...

不好意思还是没太明白,为啥字典a 变了之后再append,已经加进去的那个a也跟着变了,第一个a加进去了就是加进去了,加的就是当时的a,a改变是之后的事情啊,程序不是顺着读的吗?难道后面a的更改能影响第一个append的a?

关于sorted,我想是因为字典无序,每次加入元素是不是可能会打乱顺序?这样打印出来就不是按照行号的了。或者打印的时候可能会无序?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-17 23:50

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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