日记大全

日记大全 > 句子大全

序列对象和文本内容的相似性分析

句子大全 2015-04-15 04:11:09
相关推荐

Python提供了计算序列对象和文本间差异的辅助工具difflib,difflib提供了用于比较序列的类和函数。difflib有三个主要的类,分别是SequenceMatcher类、Differ类和HtmlDiff类。

SequenceMatcher类

SequenceMatcher类可用于比较任何类型的序列对象,只要序列元素为 hashable 对象。

SequenceMatcher类的构造方法如下:

difflib.SequenceMatcher(isjunk=None, a="", b="", autojunk=True)

参数 isjunk 必须为 None (默认值) 或为一个函数,该函数接收一个序列元素,传入的元素为应忽略的“垃圾”元素时,该函数返回真值。所谓“垃圾”元素是指其在某种意义上没有价值,例如空白行或空白符。,传入 None 作为 isjunk 的值就相当于传入 lambda x: False;也就是说不忽略任何值。

例如当对字符序列进行比较时,若不希望区分空格符或制表符。Isjunk参数传入的值可以为lambda表达式:

lambda x: x in " \t"

或者传入下面的函数:

def is_space(x):return x in " \t"

可选参数 a 和 b 为要比较的序列;两者默认为空字符串。两个序列的元素都必须为 hashable。

SequenceMatcher类提供了下面的方法:

set_seq1(a)

设置要比较的第一个序列,参数a为要设置的序列。

set_seq2(b)

设置要比较的第二个序列,参数b为要设置的序列。

find_longest_match(alo, ahi, blo, bhi)

找出 a[alo:ahi] 和 b[blo:bhi] 中的最长匹配块。方法返回一个命名元组类型 Match(a, b, size),元组名称为Match。命名元组继承自元组类型,可以通过元组名称来访问元组的元素。

例如:Match.a和Match[0]都是访问元组的第一个元素a。

参数alo, ahi为第一个序列对象的索引,blo, bhi为第二个序列对象的索引。若类构造方法的参数 isjunk 被省略或为 None,函数将返回 (i, j, k) 使得 a[i:i+k] 等于 b[j:j+k],其中 alo <= i <= i+k <= ahi 并且 blo <= j <= j+k <= bhi。

例如:# 导入difflib模块import difflib as diff# 构造SequenceMatcher实例对象s = diff.SequenceMatcher(None, " abcd", "abcd abcd")# 匹配第一个字符串abcd和第二个字符串abcd abcd相同的部分# 第一个字符的起始索引为0,终止索引为5# 第二个字符的起始索引为0,终止索引为9m = s.find_longest_match(0, 5, 0, 9)print(m)程序执行结果为:Match(a=0, b=4, size=5)

若构造对象时提供了isjunk,将按上述规则确定第一个最长匹配块,但匹配过程中会忽略垃圾字符。

下面的案例提供了isjunk,并将空格视为垃圾字符。这将防止 " abcd" 直接与第二个序列末尾的 " abcd" 相匹配。 而只可以匹配 "abcd",并且是匹配第二个序列最左边的 "abcd"。

# 构造SequenceMatcher实例对象,设置空格为垃圾字符s = diff.SequenceMatcher(lambda x: x==" ", " abcd", "abcd abcd")

get_matching_blocks()

该方法找出第一个字符串与第二个字符串所有相同的子序列,返回值为命名的三元组列表Match(i,j,n),每个三元组的形式为 (i, j, n),其含义为 a[i:i+n] == b[j:j+n]。 这些三元组按 i 和 j 单调递增排列。

最后一个三元组用于占位,其值为 (len(a), len(b), 0)。 它是唯一 n == 0 的三元组。

s = diff.SequenceMatcher(None, "abxcd", "abcd")# 找出第一个字符串与第二个字符串所有相同的子序列m = s.get_matching_blocks()

程序执行结果如下所示:

[Match(a=0, b=0, size=2), Match(a=3, b=2, size=2), Match(a=5, b=4, size=0)]

get_opcodes()

该方法返回一个命名的5元组列表,该5元组列表描述了如何将a转换为b。每个元组的形式为 (tag, i1, i2, j1, j2)。 在第一个元组中 i1 = =j1 == 0,而在其余的元组中 i1 等于前一个元组的 i2,并且 j1 也等于前一个元组的 j2。

tag的值为字符串,其含义如下:

a = "qabxcd"b = "abycdf"# 构造SequenceMatcher对象s = diff.SequenceMatcher(None,a,b)# 输出5元组的值for tag, i1, i2, j1, j2 in s.get_opcodes():print("{} a[{}:{}] --> b[{}:{}] {!r} --> {!r}".format(tag, i1, i2, j1, j2, a[i1:i2], b[j1:j2]))ratio()

返回一个取值范围 [0, 1] 的浮点数作为序列相似性度量。

调用该方法之前,需要先调用get_matching_blocks() 或 get_opcodes()方法,会获得比较好的性能。

print("abxcd 与 abcd的相似度为:%.2f" % (s.ratio()))

quick_ratio()

相对快速地返回一个序列相似性度量。

real_quick_ratio()

非常快速地返回一个序列相似性度量。

这三个返回序列相似性度量的方法,可能因返回匹配部分占字符总数的比率的方法,由于不同的近似级别而给出不一样的结果,但是 quick_ratio() 和 real_quick_ratio() 总是会至少与 ratio() 一样大

print("ratio():abxcd 与 abcd的相似度为:%.2f" % (s.ratio()))print("quick_ratio():abxcd 与 abcd的相似度为:%.2f" % (s.quick_ratio()))print("real_quick_ratio():abxcd 与 abcd的相似度为:%.2f" % (s.real_quick_ratio()))

程序执行结果如下:

ratio():abxcd 与 abcd的相似度为:0.89quick_ratio():abxcd 与 abcd的相似度为:0.89real_quick_ratio():abxcd 与 abcd的相似度为:0.89

阅读剩余内容
网友评论
相关内容
拓展阅读
最近更新