Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 查找文件中最相似的行_Python_Difflib - Fatal编程技术网

Python 查找文件中最相似的行

Python 查找文件中最相似的行,python,difflib,Python,Difflib,该程序的目的是收集计算机上所有程序的列表,并根据用户输入找到正确的路径。因此,如果输入是试听,程序将返回 C:\Adobe\Audition CC 2014\Audition CC 2014.exe 我需要它来搜索一个txt文件的一行,这是最类似的用户输入。我的代码如下: 导入操作系统 导入子流程 导入getpass 导入系统 导入difflib 从difflib导入SequenceMatcher作为SM user=getpass.getuser printos.getcwd exeFile=o

该程序的目的是收集计算机上所有程序的列表,并根据用户输入找到正确的路径。因此,如果输入是试听,程序将返回 C:\Adobe\Audition CC 2014\Audition CC 2014.exe

我需要它来搜索一个txt文件的一行,这是最类似的用户输入。我的代码如下:

导入操作系统 导入子流程 导入getpass 导入系统 导入difflib 从difflib导入SequenceMatcher作为SM user=getpass.getuser printos.getcwd exeFile=os.getcwd+/path/programpath.txt def get_文件路径目录: 文件路径=[]列表,该列表将存储所有完整的文件路径。 exes=openos.getcwd+/path/programpaths.txt,w+ 在树上散步。 对于os.walkdirectory中的根目录、目录和文件: 对于文件中的文件名: 连接两个字符串以形成完整的文件路径。 filepath=os.path.joinroot,文件名 file_path.appendfilepath将其添加到列表中。 如果filepath.endswith'exe'和n安装不在filepath中,并且$RECYCLE.BIN不在filepath中: files=filepath.encode'cp850',errors='replace'。decode'cp850' 打印文件+\n exes.writefiles+\n 返回文件路径自解释。 如果不是os.path.existsexeFile: 打印列表编译应该只发生一次 打印 打印已安装程序的列表 打印这可能需要一些时间 exes=openos.getcwd+/path/programpaths.txt,一个+ 完整\u文件\u路径x64=获取\u文件路径'C:\Program Files' 完整\u文件\u路径x86=获取\u文件路径'C:\Program Files x86' full\u file\u pathsgames=get\u filepath'G:\\' 运行上述函数并将其结果存储在变量中。 打印列表编译应该只发生一次 打印 打印完毕! pinput=输入 对于openexeFile中的行: prog=行分割\\[-1] sim=difflib.get\u close\u matchespinput[prog],1 普林西姆 但是,这会为文件中的每一行打印一个空括号[],而不仅仅是提供我需要的那一行

我知道这是因为我告诉它对每一行执行此操作,但我不知道如何解决此问题。

get\u close\u匹配…,1次调用将返回一个空列表,或一个正好匹配的列表

您想用英语做的是:

如果它有一个元素,打印它。 否则,什么都不要做。 将其直接转换为python:

if sim:
    print(sim[0])
你可以写其他的东西:换个说法,什么都不要做,或者你什么都不能写

这解决了以下问题:不要打印每一行的[],只打印匹配项

但这也带来了另一个问题:你实际上没有得到任何匹配

正如poke在评论中解释的那样,获取_close_匹配的第二个参数是一个要检查的可能性列表,但是您传递的值prog是一个字符串

如果不清楚为什么是单个字符串,请查看以下行:

prog = line.split("\\")[-1]
您将字符串拆分为一个较小字符串的列表,然后只取最后一个带有[-1]的字符串

如果您想知道为什么没有得到错误:字符串本身就是一个字符串序列,每个字符对应一个字符串。所以,如果prog是abcde,那么你要求它将['a','b','c','d','e']视为5种不同的可能性,这是一种完全合理的做法,它不太可能匹配任何东西

我想你想要的可能只是传递一个可能性列表:

sim = difflib.get_close_matches(pinput, [prog], 1)
或者,您也可以建立一个包含所有可能性的大列表,而不是一次搜索一个可能性,然后一次搜索所有可能性:

progs = []
for line in open(exefile):
    progs.append(line.split("\\")[-1])
sim = difflib.get_close_matches(pinput, progs, 1)
但在整个文件中,这只得到1个匹配总数,而不是每行1个可能的匹配。如果你想要一个以上的总数,你可以这样做,但我不确定它对一个巨大的数字有多有效。你可以试试看

无论如何,希望你明白你真正想要的是什么,而不必猜测

get_close_matches…,1调用将返回一个空列表或一个正好匹配的列表

您想用英语做的是:

如果它有一个元素,打印它。 否则,什么都不要做。 将其直接转换为python:

if sim:
    print(sim[0])
你可以写其他的东西:换个说法,什么都不要做,或者你什么都不能写

这解决了以下问题:不要打印每一行的[],只打印匹配项

但这也带来了另一个问题:你实际上没有得到任何匹配

正如poke在评论中解释的那样,获取_close_匹配的第二个参数是一个要检查的可能性列表,但是您传递的值prog是一个字符串

如果不清楚为什么是单个字符串,请查看以下行:

prog = line.split("\\")[-1]
您将字符串拆分为一个较小字符串的列表,然后只取最后一个带有[-1]的字符串

如果您想知道为什么没有得到错误:字符串本身就是一个字符串序列,每个字符对应一个字符串。所以,如果prog是abcde,那么你要求它治疗['a','b','c' ,'d','e']作为5种独立的可能性,这是一种完全合理的做法,它不太可能匹配任何东西

我想你想要的可能只是传递一个可能性列表:

sim = difflib.get_close_matches(pinput, [prog], 1)
或者,您也可以建立一个包含所有可能性的大列表,而不是一次搜索一个可能性,然后一次搜索所有可能性:

progs = []
for line in open(exefile):
    progs.append(line.split("\\")[-1])
sim = difflib.get_close_matches(pinput, progs, 1)
但在整个文件中,这只得到1个匹配总数,而不是每行1个可能的匹配。如果你想要一个以上的总数,你可以这样做,但我不确定它对一个巨大的数字有多有效。你可以试试看


无论如何,希望你明白你真正想要的是什么,而不必猜测

了解你真正想要做的事情总是好的

首先用字符串定义最接近的时间是什么意思,这称为汉明距离

def hamming_distance(s1,s2):
    #first elimate non-letters
    s1 = re.sub("[^a-zA-Z]","",s1)
    s2 = re.sub("[^a-zA-Z]","",s2)
    #the distance is the sum of all instance with differing letters in this case
    return sum(a!=b for a,b in izip_longest(s1,s2))
然后,您只需在该文件上迭代并找到最接近的匹配项

user_input = input("Enter String:")
print(min(open("file_of_strings.txt"),key=lambda x:hamming_distance(x,user_input)))

当然,一旦你了解了它的神奇之处,你可能会使用difflib获得一个边际的加速比,了解你真正想要做的事情总是很好的

首先用字符串定义最接近的时间是什么意思,这称为汉明距离

def hamming_distance(s1,s2):
    #first elimate non-letters
    s1 = re.sub("[^a-zA-Z]","",s1)
    s2 = re.sub("[^a-zA-Z]","",s2)
    #the distance is the sum of all instance with differing letters in this case
    return sum(a!=b for a,b in izip_longest(s1,s2))
然后,您只需在该文件上迭代并找到最接近的匹配项

user_input = input("Enter String:")
print(min(open("file_of_strings.txt"),key=lambda x:hamming_distance(x,user_input)))
一旦你了解了它的神奇之处,你就可以使用difflib获得一个边际的加速。如果你的exefile候选列表很小,那么就把它们预加载到列表中的内存中,然后执行difflib.get\u close\u匹配,例如:

在上侧,如果它非常大,并且您无法支持RAM,则使用heapq:

import difflib, heapq

with open(exefile) as fin:
    progs = (line.rpartition('\\'), line)[2] for line in fin)
    sim = heapq.nlargest(1, progs, key=lambda L: difflib.SequenceMatcher(None, pinput, L))
如果exefile候选列表很小,则将它们预加载到列表中的内存中,然后执行difflib.get\u close\u匹配,例如:

在上侧,如果它非常大,并且您无法支持RAM,则使用heapq:

import difflib, heapq

with open(exefile) as fin:
    progs = (line.rpartition('\\'), line)[2] for line in fin)
    sim = heapq.nlargest(1, progs, key=lambda L: difflib.SequenceMatcher(None, pinput, L))

我在文档中查找get_close_匹配项。第二个参数似乎应该是list,因此您的代码可以写成:

for line in open(exefile):
    prog = line.split("\\")[-1]
    prog = [item for item in prog.split(' ')]
    sim = difflib.get_close_matches(pinput, prog, 1)
    print(sim) 

我在文档中查找get_close_匹配项。第二个参数似乎应该是list,因此您的代码可以写成:

for line in open(exefile):
    prog = line.split("\\")[-1]
    prog = [item for item in prog.split(' ')]
    sim = difflib.get_close_matches(pinput, prog, 1)
    print(sim) 
试试这个:

with open(exefile) as f:
    possibilities = [line.split("\\")[-1].rstrip("\n") for line in f]
print(difflib.get_close_matches(pinput, possibilities, 1, 0)[0])
这里的关键是get_close_matches根本不需要返回任何匹配。从文档中:

接近匹配词,可能性[,n][,截止]

截止默认值0.6是[0,1]范围内的浮点值。不得分至少与word相似的可能性将被忽略

因此,如果使用cutoff=0,get_close_matches必须返回一些东西-最佳匹配。

尝试以下方法:

with open(exefile) as f:
    possibilities = [line.split("\\")[-1].rstrip("\n") for line in f]
print(difflib.get_close_matches(pinput, possibilities, 1, 0)[0])
这里的关键是get_close_matches根本不需要返回任何匹配。从文档中:

接近匹配词,可能性[,n][,截止]

截止默认值0.6是[0,1]范围内的浮点值。不得分至少与word相似的可能性将被忽略


因此,如果您使用cutoff=0,get_close_matches必须返回一些东西-最佳匹配。

根据您现在发布的完整代码,这是我的解决方案,可能是解决您问题的最佳方法:

with open(exeFile) as f:
    programs = { path.rsplit('\\', 1)[-1].rstrip()[:-4].lower(): path.strip() for path in f }

sim = difflib.get_close_matches(pinput.lower(), programs.keys(), 1)
if sim:
    print(programs[sim[0]])
魔法发生在字典理解上。对于文件中的每个路径,我们生成以下名称,作为字典条目的键:

path.rsplit('\\', 1)[-1][:-4].lower()
因此,假设文件路径类似于C:\Adobe\Audition CC 2014\Audition CC 2014.exe,它将首先从右侧斜杠处拆分一次,并获取最后一个元素,因此我们将获得Audition CC 2014.exe。接下来,我们去掉空白,然后根据生成exe文件的方式去掉文件名中的.exe。所以我们有2014年的海选。接下来,我们将其小写,这样我们就有了更好的可比性,因为difflib是区分大小写的

在比较中,我们只需从字典的键中获得接近的匹配项,字典的键就是小写的程序名。我们将其与小写的用户输入进行比较


得到结果后,我们将打印属于匹配密钥的路径。这就是我们在上面建立词典的原因;否则,我们将不得不再次搜索文件以找到完整路径。

根据您现在发布的完整代码,这是我的解决方案,可能是解决您问题的最佳方法:

with open(exeFile) as f:
    programs = { path.rsplit('\\', 1)[-1].rstrip()[:-4].lower(): path.strip() for path in f }

sim = difflib.get_close_matches(pinput.lower(), programs.keys(), 1)
if sim:
    print(programs[sim[0]])
魔法发生在字典理解上。对于文件中的每个路径,我们生成以下名称,作为字典条目的键:

path.rsplit('\\', 1)[-1][:-4].lower()
因此,假设文件路径类似于C:\Adobe\Audition CC 2014\Audition CC 2014.exe,它将首先从右侧斜杠处拆分一次,并获取最后一个元素,因此我们将获得Audition CC 2014.exe。接下来,我们去掉空白,然后根据生成exe文件的方式去掉文件名中的.exe。所以我们有2014年的海选。接下来,我们将其小写,这样我们就有了更好的可比性,因为difflib是区分大小写的

在比较中,我们只需从字典的键中获得接近的匹配项,字典的键就是小写的程序名。我们将其与低成本进行比较 er案例用户输入



得到结果后,我们将打印属于匹配密钥的路径。这就是我们在上面建立词典的原因;否则我们将不得不再次搜索该文件以找到完整路径。

您介意发布函数difflib.get_close_matches的代码吗?@galaxyan它在标准库中。。。并记录了。。。OP不需要发布Prog是一个字符串,但应该是一个可能性序列。所以它被解释为一个字符列表。@poke:好的。这听起来不像是他要问的问题,但他也必须解决这个问题……我不知道他是指“pinput,[prog],1”还是[:-1],而不是[-1]或前一行的什么≥@如果不是更好的解决方案,可能是get_close_MatchesInput,file.splitlines,1您介意发布函数difflib.get_close_matches的代码吗?@galaxyan它在标准库中。。。并记录了。。。OP不需要发布Prog是一个字符串,但应该是一个可能性序列。所以它被解释为一个字符列表。@poke:好的。这听起来不像是他要问的问题,但他也必须解决这个问题……我不知道他是指“pinput,[prog],1”还是[:-1],而不是[-1]或前一行的什么≥@abarnert更好的解决方案可能是get_close_MatchesInput,file.splitlines,1这完全有道理,但我对python非常陌生,所以请耐心听我说。我把它放在我的代码里,它根本不打印任何东西。谢谢你的帮助@瑞安·安德森:看起来你还有另一个问题,除此之外,可能就是普克在评论中指出的那个问题。我将编辑答案来解释。@RyanAnderson:对不起,花了这么长时间;请参阅新的编辑。@ap:不幸的是,不再那么简洁了:@abarnert嘿,这听起来正是我所需要的,我真的很感谢你的帮助,但我似乎仍然无法克服这个困难。为了澄清,我确实希望从文件中获得最接近的匹配。只有一场比赛。我更新了我原来的帖子,希望能帮助你们帮助我。再次感谢!这完全有道理,但我对python非常陌生,所以请耐心听我说。我把它放在我的代码里,它根本不打印任何东西。谢谢你的帮助@瑞安·安德森:看起来你还有另一个问题,除此之外,可能就是普克在评论中指出的那个问题。我将编辑答案来解释。@RyanAnderson:对不起,花了这么长时间;请参阅新的编辑。@ap:不幸的是,不再那么简洁了:@abarnert嘿,这听起来正是我所需要的,我真的很感谢你的帮助,但我似乎仍然无法克服这个困难。为了澄清,我确实希望从文件中获得最接近的匹配。只有一场比赛。我更新了我原来的帖子,希望能帮助你们帮助我。再次感谢!这太棒了!非常感谢你!然而,我们似乎还有最后一个问题:准确性。例如,键入Audition返回G:\Steam\SteamApps\common\Plants vs.Zombies\Plants vs.Zombies.exe再次感谢您的帮助是的,difflib的准确性或缺乏准确性。您可以尝试使用截断参数,看看它是否有帮助。否则,您可能需要研究不同的比较策略,例如使用levenshtein距离或其他类型的模糊匹配。这太棒了!非常感谢你!然而,我们似乎还有最后一个问题:准确性。例如,键入Audition返回G:\Steam\SteamApps\common\Plants vs.Zombies\Plants vs.Zombies.exe再次感谢您的帮助是的,difflib的准确性或缺乏准确性。您可以尝试使用截断参数,看看它是否有帮助。否则,您可能需要研究不同的比较策略,例如使用levenshtein距离或其他类型的模糊匹配