鱼C论坛

 找回密码
 立即注册
查看: 955|回复: 11

[已解决]用已建立好的词典找目标文件中的匹配项 小报错,望解答 给您鱼币 谢谢

[复制链接]
发表于 2020-2-14 22:30:24 | 显示全部楼层 |阅读模式

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

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

x
大家过年好!!!
        我建立了一个词典1.txt,其内容大致是:
Y_A,Fb11
Y_E,Fb11
VY_A,Fb11
0Y_A,Fb11
UY_E,Fb11
(Key是逗号前的(词缀),Value是逗号后的内容(词缀标记))


然后我想在我的目标文件2.txt中找到匹配项目,匹配的要求是,再2.txt文件中以词的后面开始匹配,因为1.txt是词缀文件。我的2.txt大致内容:
YABVY_A
AAAUY_E
VVVVY_A
SA0Y_A

最终想要得到 YABV/Y_A(Fb11),AAA/UY_E(Fb11)这样的以“/”区分并标注的文件。谢谢您了。我的鱼币不多,希望给新手解答。

以下是我做的词典的代码尝试:
dicFile = open('1.txt', 'r')  # 打开数据
print('开始装载数据...')
txtDict = {}  # 建立字典
while True:
    line = dicFile.readline()
    if line == '':
        break
    index = line.find(',')  # 以“,”键为分割
    key = line[:index]
    value = line[index:]
    txtDict[key] = value  # 加入字典
dicFile.close()
最佳答案
2020-2-15 00:37:30
本帖最后由 shangjiecat 于 2020-2-15 15:43 编辑
  1. #1.txt字典建立部分
  2. print('开始装载数据...')
  3. with open('1.txt', 'r') as dicFile:
  4.     txtDict = {}  # 建立字典
  5.     for line in dicFile:
  6.         li = line.split(',')
  7.         txtDict[li[0]] = li[1].strip("\n")  # 加入字典

  8. #匹配部分
  9. search = open('2.txt', 'r')
  10. for line in search:  #对2.txt的每一行单独查找
  11.     line = line.strip("\n")   #去掉换行号
  12.     part = ''  #初始化判断条件
  13.     x = 0
  14.     for key in txtDict:  #从字典里遍历键
  15.         length = len(key)  #获取字典键长
  16.         if key in line:  #如果一行的字符串里有key值,把key变成0(如YABVY_A变成YAB0)
  17.             nline = line.replace(key,'0')
  18.         else:  #没有则查找下一个键
  19.             continue
  20.         if nline[-1] == '0' and x < length:  #如果末尾有0,说明替换成功,判断新后缀长度与已存后缀哪个长
  21.             nline = nline.replace('0',key,line.count(key)-1)  #增加防止VY_AVY_AVY_A类的出现,因此反替换
  22.             #(最后一个不替换,保留)
  23.             x = length  #因为被替换,把该后缀长度存入x,用于判断是否有更长的后缀
  24.             part = nline[:-1] +"/"+ key + "(%s)"%txtDict[key]  #输出需要的格式字符串
  25.     inf = line if part == '' else part  #如果没有则直接输出该行的判断
  26.     print(inf,end = ',')
  27. search.close()
复制代码

输出如下
  1. 开始装载数据...
  2. YAB/VY_A(Fb11),AAA/UY_E(Fb11),VVV/VY_A(Fb11),SA/0Y_A(Fb11),SSSO_E, #最后一个是不存在的情况,应该是这个意思吧?
复制代码

考虑如果楼主是初学者原因,语句没有难理解的那种,然后就得用到很多循环,代码显得层层叠叠,不知道会不会有更好的想法,也不知道能不能满足楼主需求,如有疑问或要改进,欢迎回复!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-2-15 00:37:30 | 显示全部楼层    本楼为最佳答案   
本帖最后由 shangjiecat 于 2020-2-15 15:43 编辑
  1. #1.txt字典建立部分
  2. print('开始装载数据...')
  3. with open('1.txt', 'r') as dicFile:
  4.     txtDict = {}  # 建立字典
  5.     for line in dicFile:
  6.         li = line.split(',')
  7.         txtDict[li[0]] = li[1].strip("\n")  # 加入字典

  8. #匹配部分
  9. search = open('2.txt', 'r')
  10. for line in search:  #对2.txt的每一行单独查找
  11.     line = line.strip("\n")   #去掉换行号
  12.     part = ''  #初始化判断条件
  13.     x = 0
  14.     for key in txtDict:  #从字典里遍历键
  15.         length = len(key)  #获取字典键长
  16.         if key in line:  #如果一行的字符串里有key值,把key变成0(如YABVY_A变成YAB0)
  17.             nline = line.replace(key,'0')
  18.         else:  #没有则查找下一个键
  19.             continue
  20.         if nline[-1] == '0' and x < length:  #如果末尾有0,说明替换成功,判断新后缀长度与已存后缀哪个长
  21.             nline = nline.replace('0',key,line.count(key)-1)  #增加防止VY_AVY_AVY_A类的出现,因此反替换
  22.             #(最后一个不替换,保留)
  23.             x = length  #因为被替换,把该后缀长度存入x,用于判断是否有更长的后缀
  24.             part = nline[:-1] +"/"+ key + "(%s)"%txtDict[key]  #输出需要的格式字符串
  25.     inf = line if part == '' else part  #如果没有则直接输出该行的判断
  26.     print(inf,end = ',')
  27. search.close()
复制代码

输出如下
  1. 开始装载数据...
  2. YAB/VY_A(Fb11),AAA/UY_E(Fb11),VVV/VY_A(Fb11),SA/0Y_A(Fb11),SSSO_E, #最后一个是不存在的情况,应该是这个意思吧?
复制代码

考虑如果楼主是初学者原因,语句没有难理解的那种,然后就得用到很多循环,代码显得层层叠叠,不知道会不会有更好的想法,也不知道能不能满足楼主需求,如有疑问或要改进,欢迎回复!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-15 01:10:36 | 显示全部楼层
楼主的规则不明,第一条结果是:YABV/Y_A(Fb11)而不是YAB/VY_A(Fb11),为什么和Y_A匹配而不是VY_A匹配?不说明这点,后半部的匹配工作是无法完成的。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-15 11:21:32 | 显示全部楼层
shangjiecat 发表于 2020-2-15 00:37
输出如下

考虑如果楼主是初学者原因,语句没有难理解的那种,然后就得用到很多循环,代码显得层层叠叠 ...

    1.您好,真心谢谢您,看了您的回复后我又尝试了很多,最终得到了终极的语法规则。其语法规则是,从一个词的后面,也就是反向匹配,匹配时需要最大匹配,最大匹配的意思是,不要从一个词的后面-1的匹配。哈哈哈,因为是新手说的可能不是标准,我尽量表达清楚。
    2.用例子说的话:AAAVY_A这个词,如果每次从后面去掉一个字母(-1)的原则匹配的话最终是能匹配到Y_A这个词缀,但是词缀词典里有VY_A这个词缀。所以我想从反向的去最大匹配。这样就能解决怎么匹配的问题了。
    3.考虑到一个词可能有多个词缀,所以最终我想加一个循环,从一个词的后面开始多次最大匹配标记。是否能解决呢?真心谢谢,大神您就当练练手吧 哈哈哈,谢谢,谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-15 11:25:51 | 显示全部楼层
txxcat 发表于 2020-2-15 01:10
楼主的规则不明,第一条结果是:YABV/Y_A(Fb11)而不是YAB/VY_A(Fb11),为什么和Y_A匹配而不是VY_A匹配?不 ...

    1.您好,谢谢您的回复,您的回复点醒了我,经过多次尝试,我确定的最终的语法规则,其语法规则是从每个词的后面,也就是反面的匹配,匹配是需要最大匹配,最大匹配的意思是,不要从一个词的后面-1的匹配。哈哈哈,因为是新手说的可能不是标准,我尽量表达清楚。
    2.用例子说的话:AAAVY_A这个词,如果每次从后面去掉一个字母(-1)的原则匹配的话最终是能匹配到Y_A这个词缀,但是词缀词典里有VY_A这个词缀。所以我想从反向的去最大匹配。这样就能解决怎么匹配的问题了。
    3.考虑到一个词可能有多个词缀,所以最终我想加一个循环,从一个词的后面开始多次最大匹配标记。是否能解决呢?真心谢谢,大神您就当练练手吧 哈哈哈,谢谢,谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-15 12:41:59 | 显示全部楼层
本帖最后由 shangjiecat 于 2020-2-15 12:51 编辑
Amgalang 发表于 2020-2-15 11:21
1.您好,真心谢谢您,看了您的回复后我又尝试了很多,最终得到了终极的语法规则。其语法规则是,从一 ...


我的代码已经实现最大匹配了,
x < length的条件就是寻找最长的词缀,如果找到了就会把短词缀替换,不信你试试(如果你觉得代码符合条件了,希望在代码那给个最佳答案哦
(PS:在代码那加了个with打开文件,写了这个文件会不用时自动关闭)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-15 14:38:35 | 显示全部楼层
shangjiecat 发表于 2020-2-15 12:41
我的代码已经实现最大匹配了,
x < length的条件就是寻找最长的词缀,如果找到了就会把短词缀替换,不 ...

1.谢谢,已给予最佳答案,正在学习代码中,因为是初学者,想请教两个问题,这个代码是反向匹配的吗?希望您有空时写个详细注释,哈哈哈。
2.目前代码运行起来后,9000个数据的文件跑起来,越来越慢了。效果是:《$00BIN/G(Fi3),未找到匹配项,未找到匹配项,未找到匹配项,未找到匹配项,$0BT0R/0GAD(Fi3),$/0G(Fi3)》......这个样子,能否把“未找到匹配项去掉,把未找到匹配项的词原封不动的显示出来呢”。这是最后一问了,谢谢谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-15 15:22:23 | 显示全部楼层
本帖最后由 shangjiecat 于 2020-2-15 16:36 编辑
Amgalang 发表于 2020-2-15 14:38
1.谢谢,已给予最佳答案,正在学习代码中,因为是初学者,想请教两个问题,这个代码是反向匹配的吗?希望 ...


注释已经写了,你可以再研究研究,你要的原样输出也改了,还有刚刚的代码value输出有错误,已改正
另外,字典部分若你的文档无更改,为了避免重复运行,可以把字典先存到一个文件,避免重复存储,在匹配板块再打开存储文件读取加载
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-15 20:26:18 | 显示全部楼层
shangjiecat 发表于 2020-2-15 15:22
注释已经写了,你可以再研究研究,你要的原样输出也改了,还有刚刚的代码value输出有错误,已改正
另 ...

1.您好,我想认识下您,我是一名在读自然语言处理博士生,我更加侧重语言学,所以计算机方面弱,如若可以以后咱们一起做项目。我的微信号:M1556434735。
2.不好意思,我厚着脸皮在请教您一个问题,见谅见谅,希望满足一个初学者,哈哈哈。刚刚我发现了一个重要缺陷,就是,如果不能在一个词内重复匹配,那就无意义了。意识就是说,如:YAB0VY_AY_A一词,期望的分析是YAB0/VY_A/Y_A(Fb11,Fb11)一个词可以多次分析直到无匹配项。这样就真的很完美了,我自己在乱查百度,希望您有空 指点代码,谢谢谢谢谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-15 20:37:57 | 显示全部楼层
shangjiecat 发表于 2020-2-15 15:22
注释已经写了,你可以再研究研究,你要的原样输出也改了,还有刚刚的代码value输出有错误,已改正
另 ...

不好意思,不好意思,您先别考虑 我回复您的《2.》我的语法有误。不好意思。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-16 12:44:22 | 显示全部楼层
  1. search = open('2.txt', 'r')
  2. def parting(s):
  3.     global d_li
  4.     part = ''  #初始化判断条件
  5.     x = 0
  6.     y = len(s)-1
  7.     for key in txtDict:  #从字典里查找键与值
  8.         length = len(key)  #获取字典键长
  9.         if key in s and key != s:
  10.             if s.count(key) == 1:
  11.                 nline = s.replace(key,'*')
  12.             else:
  13.                 nline = s.replace(key,'*',s.count(key)-1)
  14.             l_index = nline.index('*')
  15.         else:
  16.             continue
  17.         if y > l_index and x < length:  #判断新后缀长度与已存后缀哪个长
  18.             x = length  #因为被替换,把该后缀长度存入x,用于判断是否有更长的后缀
  19.             y = l_index
  20.             z = len(nline)-1
  21.             if y == z:
  22.                 part = nline[:-1] +"/"+ key  #输出需要的格式字符串
  23.             elif y != 0:
  24.                 part = nline[:y] +'/' +key +'%'
  25.             else:
  26.                 part = key +'%'
  27.             n_key = key
  28.             n_line = nline[nline.index('*')+1:]
  29.     if '/' in part or '%' in part:
  30.         d_li.append(txtDict[n_key])
  31.     if '%' in part:
  32.         partx = parting(n_line)
  33.         if partx == '':
  34.             part += n_line
  35.         else:
  36.             part += partx
  37.     if '%' in part:
  38.         part = part.replace('%','/')
  39.     return part
  40.                
  41. for line in search:  #对2.txt的每一行单独查找
  42.     line = line.strip("\n")   #去掉换行号
  43.     d_li = []
  44.     part = parting(line)
  45.     part += str(tuple(d_li))
  46.     inf = line if '/' not in part else part
  47.     print(inf,end = ',')
  48. search.close()
复制代码

匹配部分修改
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-12-16 08:59:05 | 显示全部楼层
学习一下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-27 08:07

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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