yangxuebabe 发表于 2020-4-22 17:36:32

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


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

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

import os

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

def search_keyword(keyword) :   
    all_files = os.listdir(os.curdir)
   
    for each_file in all_files:
      ext = os.path.splitext(each_file)
      
      if os.path.isdir(each_file) :
            os.chdir(each_file)
            search_keyword(keyword)   
            os.chdir(os.pardir)
            
      if ext == '.txt':
            path = os.getcwd() + os.sep + each_file   # path保存文本文件路径
            f = open(each_file)
            line_site = dict()   # 存放每个关键字{行:列}的字典,每个新文件都要置空
            line_num = 0
            
            for each_line in f:
                site_num = []    # 存放【列】的列表,每一行查找时都要置空
                line_num += 1    # 每行的行数每次 +1
               
                while 1:
                  i = 0
                  site = each_line.find(keyword, i)   # 查找关键字,如果有返回关键字的第一个索引号(即列),没有返回-1
                  if site != -1:             # 查到关键字
                        site_num.append(site)# 将关键字的第一个索引号即列值加入列表中
                        i = site + 1         # 从site后一个位置查找这一行还有没有关键字(11在1111中的数目
                  else:                      # 如果没有找到关键字
                        break                  # 说明each_line这一行检索完毕或根本没有关键字,退出while循环查找下一行
                        
                if site_num == []:                  # 如果【列】的列表是空的,说明这一行没有关键字
                  continue                        # 继续查找下一行
                else:                               # 如果【列】的列表不是空的,说明这一行有关键字
                  line_site = site_num# 在字典中添加{行数(数字):列数【列表】}
                  each_txt.append(line_site)      # 在这个文件的列表中添加字典
                  
            if line_site == {}:      # 如果字典是空的,说明没有{行:列}添加,即此文件中没有关键字
                continue             # 退出查找每行的for循环,查找下一文件
            else:                  # 如果字典不是空的,说明有{行:列}添加,即此文件中有关键字
                paths.append(path)   # 添加此文件的路径
               
            f.close()
            
keyword = input('请将该脚本放于待查找的文件夹内,请输入关键字:')
search_keyword(keyword)      
decide = input('请问是否需要打印关键字【%s】在文件中大的具体位置(YES/NO):' % keyword)

if decide in ['YES', 'yes', 'Yes']:
   
    if paths == []:    # 为空说明没有存在关键字的文件
      print('===================================================')
      print('当前文件夹内所有文本文件均不含有此关键字!')
    else:
      print('===================================================')
      
      for each_path in paths:    # paths有一个元素就说明有一个文件有关键字
            print('在文件【%s】中找到关键字【%s】' % (each_path, keyword))            
            
            for each_line_site in each_txt:    # each_txt是一个列表(每个文件一个列表),每个元素each_line_site都为字典
               
                for each_item in each_line_site.items():    # each_item是字典的每一项,是一个元组(键(行),值(列))
                  print('关键字出现在第 %d 行,第' % each_item(0), each_item(1), '个位置。')# 值(列)是一个列表

txxcat 发表于 2020-4-22 18:52:38

这是个死循环:
                while 1:
                  i = 0
                  site = each_line.find(keyword, i)   # 查找关键字,如果有返回关键字的第一个索引号(即列),没有返回-1
                  if site != -1:             # 查到关键字
                        site_num.append(site)# 将关键字的第一个索引号即列值加入列表中
                        i = site + 1         # 从site后一个位置查找这一行还有没有关键字(11在1111中的数目
                  else:                      # 如果没有找到关键字
                        break                  # 说明each_line这一行检索完毕或根本没有关键字,退出while循环查找下一行

i每次循环都初始化为0,所以只要包含关键字,就成了死循环,把i=0放在外面就可以了:
                i = 0
                while 1:
                     site = each_line.find(keyword, i)   # 查找关键字,如果有返回关键字的第一个索引号(即列),没有返回-1
                  if site != -1:             # 查到关键字
                        site_num.append(site)# 将关键字的第一个索引号即列值加入列表中
                        i = site + 1         # 从site后一个位置查找这一行还有没有关键字(11在1111中的数目
                  else:                      # 如果没有找到关键字
                        break                  # 说明each_line这一行检索完毕或根本没有关键字,退出while循环查找下一行

txxcat 发表于 2020-4-22 18:59:06

顺便说一下,测试的时候碰到编码错,批量处理文本文件的时候难免碰到编码不同的文件,可以参考这个帖子改一下代码:避免打开文本文件出现编码错误的一个小技巧

yangxuebabe 发表于 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 行,第 个位置。
关键字出现在第 7 行,第 个位置。
关键字出现在第 3 行,第 个位置。
关键字出现在第 7 行,第 个位置。
关键字出现在第 17 行,第 个位置。
===================================================
在文件【F:\Python\JupyterProject\面朝大海,春暖花开.txt】中找到关键字【of】
关键字出现在第 3 行,第 个位置。
关键字出现在第 7 行,第 个位置。
关键字出现在第 3 行,第 个位置。
关键字出现在第 7 行,第 个位置。
关键字出现在第 17 行,第 个位置。

第3行和第7行是第一个文件的,打印了两次
第17行是第二个文件的

txxcat 发表于 2020-4-24 01:56:01

本帖最后由 txxcat 于 2020-4-24 01:58 编辑

yangxuebabe 发表于 2020-4-23 22:00
您好 我按照您说的修改了
但是结果还是有点问题



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

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

def copen(filename):
    try:
      f = open(filename,encoding='GBK')
      try:
            f.read()
            f.seek(0)
      except UnicodeDecodeError:
            f = open(filename,encoding='utf-8',errors='ignore')
    except (OSError,AttributeError) as reason:
      print(str(reason))
      return None
    return f

def search_keyword(keyword) :   
    all_files = os.listdir(os.curdir)
   
    for each_file in all_files:
      ext = os.path.splitext(each_file)
      
      if os.path.isdir(each_file) :
            os.chdir(each_file)
            search_keyword(keyword)   
            os.chdir(os.pardir)
            
      if ext == '.txt':
            path = os.getcwd() + os.sep + each_file
            f = copen(each_file)      #用函数copen打开防止编码错误
            line_site = dict()
            line_num = 0
            
            for each_line in f:
                site_num = []
                line_num += 1
               
                i = 0
                while 1:
                  site = each_line.find(keyword, i)
                  if site != -1:
                        site_num.append(site+1)            #python索引从0开始,人类习惯1开始
                        i = site + 1
                  else:
                        break
                        
                if site_num == []:
                  continue
                else:
                  line_site = site_num
#                  each_txt.append(line_site)          #在这里append,每找到一行就append一次,重复数据导致错误
                  
            if line_site == {}:
                continue
            else:
                paths.append(path)
                each_txt.append(line_site)               #在这里append就不会有重复数据
            f.close()

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

if decide.strip().lower()=='yes':            #这样可以对付任意大小写组合,还有空格
   
    if paths == []:
      print('===================================================')
      print('当前文件夹内所有文本文件均不含有此关键字!')
    else:
      print('===================================================')
      for i in range(len(paths)):                                       #原有的代码是有多少符合条件的文件,就把所有的答案重复打印多少次
            print('在文件【%s】中找到关键字【%s】' % (paths, keyword))   #只打印和文件对应的字典
            for j,k in each_txt.items():
                print('关键字出现在第 %d 行,第%s个位置。' % (j, k))
               
#         for each_path in paths:    # paths有一个元素就说明有一个文件有关键字
#             print('在文件【%s】中找到关键字【%s】' % (each_path, keyword))            
#            
#             for each_line_site in each_txt:    # each_txt是一个列表(每个文件一个列表),每个元素each_line_site都为字典
#               
#               for each_item in each_line_site.items():    # each_item是字典的每一项,是一个元组(键(行),值(列))
#                     print('关键字出现在第 %d 行,第' % each_item, each_item, '个位置。')# 值(列)是一个列表

yangxuebabe 发表于 2020-4-24 09:41:45

txxcat 发表于 2020-4-24 01:56
你的代码还有几处错误,看注释:

天哪太感谢了!!好细心!!

yangxuebabe 发表于 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}]

yangxuebabe 发表于 2020-4-24 13:49:00

txxcat 发表于 2020-4-24 01:56
你的代码还有几处错误,看注释:

还有一个问题。。我看了标准答案,用了sort()对字典进行排序,但是为什么我的程序没有进行排序也是自动按顺序打印的?我试了好几个关键字好多次都是按照行数顺序打印的

txxcat 发表于 2020-4-24 19:09:24

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

...

因为append的是字典变量名而不是字典的值,做个实验:
>>> a={}
>>> a['1']=1
>>> b=[]
>>> b.append(a)
>>> b
[{'1': 1}]
>>> a['2']=2
>>> a
{'1': 1, '2': 2}
>>> b.append(a)
>>> b
[{'1': 1, '2': 2}, {'1': 1, '2': 2}]
能看明白吧?不是字典如此,列表加入列表也是如此。
为什么用sorted,个人感觉没必要,因为正常情况下字典就是按行号顺序生成的。

yangxuebabe 发表于 2020-4-24 19:39:35

txxcat 发表于 2020-4-24 19:09
因为append的是字典变量名而不是字典的值,做个实验:

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

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

关于sorted,我想是因为字典无序,每次加入元素是不是可能会打乱顺序?这样打印出来就不是按照行号的了。或者打印的时候可能会无序?
页: [1]
查看完整版本: 第30讲 第4题 查找关键字的具体位置 为啥我的程序跑不对啊