3.3.2 使用SequenceMatcher对象

查找最大相同序列

例子:

#python3.4.3

 

import difflib

 

s1 = [ 1, 2, 3, 5, 6, 4 ]

s2 = [ 2, 3, 5, 4, 6, 1 ]

 

print('s1 = ', s1)

print('s2 = ', s2)

print('s1 == s2', s1 == s2)

print('')

 

matcher = difflib.SequenceMatcher(None, s1, s2)

print(matcher)

print(matcher.find_longest_match(0, 6, 0, 6))

结果输出如下:

s1 =  [1, 2, 3, 5, 6, 4]

s2 =  [2, 3, 5, 4, 6, 1]

s1 == s2 False

 

<difflib.SequenceMatcher object at 0x0299B4D0>

Match(a=1, b=0, size=3)

在这个例子里,使用了库defflib,然后创建两个列表s1s2,为了找出两个列表里最大的相同的元素长度,需要使用函数find_longest_match的功能。最后输出的结果Match(a=1, b=0, size=3),其Match是命名的元组,a是序列1,也就是列表s1b是序列2,也就是列表s2,从这里可以看到s1从第1个元素开始,s2从第0个元素开始,就可以达到最大的长度3个元素相同。

 

跳过指定的字符

在某种情况之下进行文本比较时,需要把空格去掉,只比较关心的字符,就可以采用过虑函数的功能。

例子:

#python3.4.3

 

import difflib

 

s1 = ' abcd'

s2 = 'abcd abcd'

 

print('s1 = ', s1)

print('s2 = ', s2)

print('s1 == s2', s1 == s2)

print('')

 

print('丢掉不需要空格字符:')

matcher = difflib.SequenceMatcher(lambda x: x in ' ', s1, s2)

print(matcher)

print(matcher.find_longest_match(0, 5, 0, 9))

 

print('没有丢掉不需要字符:')

matcher = difflib.SequenceMatcher(None, s1, s2)

print(matcher)

print(matcher.find_longest_match(0, 5, 0, 9))

输出结果如下:

s1 =   abcd

s2 =  abcd abcd

s1 == s2 False

 

丢掉不需要空格字符:

<difflib.SequenceMatcher object at 0x0272B4B0>

Match(a=1, b=0, size=4)

没有丢掉不需要字符:

<difflib.SequenceMatcher object at 0x0272BCF0>

Match(a=0, b=4, size=5)

 

在这个例子里,使用SequenceMatcher对象两种不同的构造形式,主要表示在isjunk是否跳过的值,这是使用函数对象来实现的,lambda是语句里声明函数的方式,xSequenceMatcher对象进行比较时传递进来的值,然后判断x是否为空格,如果是就返回True,这样SequenceMatcher对象就知道这个字符不用比较,如果返回False,就进行比较,这就是默认的情况None。因此,可以看到第一个有跳过空格的比较,是从a指向的字符第1个字符开始,而不是从0开始,从而在b指向的字符串0位置就可以匹配成功了。而第二个没有跳过空格时,a是指向的字符串是从0开始,而b指向字符串进行匹配是从4开始,也就是从空格字符开始,匹配最长的长度是5

 

使用函数set_seqs(a, b)

当你创建一个SequenceMatcher对象之后,并且使用之后又想接着比较另外一对新的序列对象,就可以使用此函数来进行设置新的比较对象,这样不用再次创建SequenceMatcher对象。

例子:

#python3.4.3

 

import difflib

 

s1 = ' abcd'

s2 = 'abcd abcd'

 

print('s1 = ', s1)

print('s2 = ', s2)

print('s1 == s2', s1 == s2)

print('')

 

print('丢掉不需要空格字符:')

matcher = difflib.SequenceMatcher(lambda x: x in ' ', s1, s2)

print(matcher)

print(matcher.find_longest_match(0, 5, 0, 9))

 

print('使用set_seqs(a, b):')

s3 = 'abcd'

s4 = 'abc abcd'

 

matcher.set_seqs(s3, s4)

print(matcher)

print(matcher.find_longest_match(0, 4, 0, 8))

结果输出如下:

s1 =   abcd

s2 =  abcd abcd

s1 == s2 False

 

丢掉不需要空格字符:

<difflib.SequenceMatcher object at 0x029BB4D0>

Match(a=1, b=0, size=4)

使用set_seqs(a, b):

<difflib.SequenceMatcher object at 0x029BB4D0>

Match(a=0, b=4, size=4)

在这个例子里可以看到,使用函数set_seqs(a, b)之后,就可以重新对新的序列s3,s4进行比较了,而不必再创建一个新的SequenceMatcher对象。

 

同一个序列跟不同其它序列进行比较,使用函数set_seq1(a)set_seq2(b) 

如果在一个序列与多个序列进行比较,可以固定一个序列不变,只变第一或第二个序列,就可以使用set_seq1(a)或者set_seq2(b)函数。

例子:

#python3.4.3

 

import difflib

 

s1 = ' abcd'

s2 = 'abcd abcd'

 

print('s1 = ', s1)

print('s2 = ', s2)

print('s1 == s2', s1 == s2)

print('')

 

print('丢掉不需要空格字符:')

matcher = difflib.SequenceMatcher(lambda x: x in ' ', s1, s2)

print(matcher)

print(matcher.find_longest_match(0, 5, 0, 9))

 

print('使用set_seq1(a):')

s3 = 'abcd'

 

matcher.set_seq1(s3)

print(matcher)

print(matcher.find_longest_match(0, 4, 0, 9))

 

s4 = 'abc abcd'

matcher.set_seq2(s4)

print(matcher)

print(matcher.find_longest_match(0, 4, 0, 8))

结果输出如下:

s1 =   abcd

s2 =  abcd abcd

s1 == s2 False

 

丢掉不需要空格字符:

<difflib.SequenceMatcher object at 0x029BB4D0>

Match(a=1, b=0, size=4)

使用set_seq1(a):

<difflib.SequenceMatcher object at 0x029BB4D0>

Match(a=0, b=0, size=4)

<difflib.SequenceMatcher object at 0x029BB4D0>

Match(a=0, b=4, size=4)

在这个例子里,通过切换不同的序列进行比较,从而得不同的输出结果。这样的速度应比重头创建一个SequenceMatcher要快一些,因为其中一个不用重新计算了。

 

get_matching_blocks()函数的使用

这个函数主要用获取ab比较序里所有相同的交集,通过一个三元组保存在一个列表里返回。

例子:

#python3.4.3

 

import difflib

 

s1 = ' abcd 123 321'

s2 = 'abcd abcd 123321'

 

print('s1 = ', s1)

print('s2 = ', s2)

print('s1 == s2', s1 == s2)

print('')

 

print('丢掉不需要空格字符:')

matcher = difflib.SequenceMatcher(lambda x: x in ' ', s1, s2)

print(matcher)

print(matcher.get_matching_blocks())

结果输出如下:

s1 =   abcd 123 321

s2 =  abcd abcd 123321

s1 == s2 False

 

丢掉不需要空格字符:

<difflib.SequenceMatcher object at 0x0278B4D0>

[Match(a=1, b=0, size=5), Match(a=6, b=10, size=3), Match(a=10, b=13, size=3), Match(a=13, b=16, size=0)]

在这个例子里,从返回的结果来看,就是在序列a[1:6]b[0:5]相同,也就是字符串“abcd ”相同;后面依次是a6位置与b10位置有3个字符相同,a10位置与b13位置有3个字符相同,最后一个表示a序列为13个字符长度,b序列为16个字符长度,size等于0用来表示最后一个三元组。

 

使用get_opcodes()函数

通过这个函数就可以查看两个序列进行比较的过程。

例子:

#python3.4.3

 

import difflib

 

s1 = ' abcd 123 321'

s2 = 'abcd abcd 123321'

 

print('s1 = ', s1)

print('s2 = ', s2)

print('s1 == s2', s1 == s2)

print('')

 

 

matcher = difflib.SequenceMatcher(None, s1, s2)

print(matcher)

 

for tag, i1, i2, j1, j2 in matcher.get_opcodes():

    print('{:7}   a[{}:{}] --> b[{}:{}] {!r:>8} --> {!r}'.format(

        tag, i1, i2, j1, j2, s1[i1:i2], s2[j1:j2]))

结果输出如下:

s1 =   abcd 123 321

s2 =  abcd abcd 123321

s1 == s2 False

 

<difflib.SequenceMatcher object at 0x0298B4D0>

insert    a[0:0] --> b[0:4]       '' --> 'abcd'

equal     a[0:9] --> b[4:13] ' abcd 123' --> ' abcd 123'

delete    a[9:10] --> b[13:13]      ' ' --> ''

equal     a[10:13] --> b[13:16]    '321' --> '321'

从上面结果来看,从s1字符串变成s2字符串需要的操作过程,先是从s10位置插入4个字符’abcd’,接着s1[0:9]s2[4:13]部分相同,接着把s1[9:10]部分删除,最后是s1[10:13]s2[13:16]相同部分。

 

使用get_grouped_opcodes(n=3)函数

这个函数是通过n来设置最长匹配值,默认为3个字符。

例子:

#python3.4.3

 

import difflib

 

s1 = ' abcd 123 321'

s2 = 'abcd abcd 123321'

 

print('s1 = ', s1)

print('s2 = ', s2)

print('s1 == s2', s1 == s2)

print('')

 

matcher = difflib.SequenceMatcher(None, s1, s2)

print(matcher)

 

for i in matcher.get_grouped_opcodes(1):

    print(i)

    print(':')

 

print('默认:')

for i in matcher.get_grouped_opcodes(9):

    print(i)

结果输出如下:

s1 =   abcd 123 321

s2 =  abcd abcd 123321

s1 == s2 False

 

<difflib.SequenceMatcher object at 0x0279B4D0>

[('insert', 0, 0, 0, 4), ('equal', 0, 1, 4, 5)]

:

[('equal', 8, 9, 12, 13), ('delete', 9, 10, 13, 13), ('equal', 10, 11, 13, 14)]

:

默认:

[('insert', 0, 0, 0, 4), ('equal', 0, 9, 4, 13), ('delete', 9, 10, 13, 13), ('equal', 10, 11, 13, 14)]

从结果上看,这个函数返回一个列表,列表里包含多个元组。参数n的值决定最长搜索的长度。

 

使用ratio() quick_ratio()real_quick_ratio()函数

计算两个比较序列的相似程度。

例子:

#python3.4.3

 

import difflib

 

s1 = ' abcd 123 321'

s2 = 'abcd abcd 123321'

 

print('s1 = ', s1)

print('s2 = ', s2)

print('s1 == s2', s1 == s2)

print('')

 

matcher = difflib.SequenceMatcher(None, s1, s2)

print(matcher)

print('ratio():', matcher.ratio())

print('quick_ratio():', matcher.quick_ratio())

print('real_quick_ratio():', matcher.real_quick_ratio())

结果输出如下:

s1 =   abcd 123 321

s2 =  abcd abcd 123321

s1 == s2 False

 

<difflib.SequenceMatcher object at 0x0298B4B0>

ratio(): 0.8275862068965517

quick_ratio(): 0.8275862068965517

real_quick_ratio(): 0.896551724137931

从结果来看,ratio的结果与quick_ratio的结果是非常接近的,但quick_ratio的速度更快一些,而real_quick_ratio的结果就差别比较大一些,但速度会更快。

 


蔡军生  微信号:shenzhencai  深圳

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

caimouse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值