比较两张vcard



我有两个vcard:

vcard1 = "BEGIN:VCARD
VERSION:3.0
N;CHARSET=UTF-8:Name;;;;
TEL:0005555000
END:VCARD"
vcard2 = "BEGIN:VCARD
VERSION:3.0
N;CHARSET=UTF-8:Name;;;;
TEL:0005555000
EMAIL;CHARSET=UTF-8:my_email@email.com
END:VCARD"

正如你所看到的,唯一的区别是第二张vcard有一个额外的属性,那就是EMAIL?使用代码,这两个vcard是否可以被视为相等?

import vobject
print(vobject.readOne(vcard1).serialize()==vobject.readOne(vcard2).serialize())

解决方案

任何比较的第一条规则是定义比较的基础。你甚至可以比较苹果和橙子,前提是你正在寻找一个可以比较的数量:比如"有多少苹果和桔子或"em>;5苹果对5个桔子的重量";。重点是对比较基础的定义必须毫不含糊。

注意:我将使用下面Dummy Data部分的数据。

将这个概念扩展到您的用例中,您可以将vcards与每个字段进行比较,然后也可以与所有字段进行比较。例如,我向您展示了三种比较它们的方法:

  • Example A1:仅在vcard1vcard2之间比较命令文件
  • Example A2:比较vcard1vcard2之间的所有文件
  • Example A3:在vcard1vcard2之间仅比较命令用户指定的文件

显然,在这种情况下,如果比较vcard1vcard2的序列化版本,它会返回False,因为这两个vcard的内容不同。

vc1.serialize()==vc2.serialize() # False

示例

在每种情况下(A1, A2, A3(,自定义函数compare_vcards()返回两件事:

  • match:一个dict,在每个字段的级别进行匹配
  • summary:一个dict,给出聚合的绝对匹配(如果所有字段都匹配(和相对匹配(比例:[0,1]((适合部分匹配(

但您必须定义自己的业务逻辑,以确定哪些匹配,哪些不匹配。不过,我在这里展示的内容应该会帮助您入门。

## Example - A1
#  Compare ONLY COMMON fields b/w vc1 and vc2
match, summary = compare_vcards(vc1, vc2, mode='common')
print(f'match:   t{match}')
print(f'summary: t{summary}')
## Output
# match:    {'n': True, 'tel': True, 'version': True}
# summary:  {'abs_match': True, 'rel_match': 1.0}
## Example - A2
#  Compare ALL fields b/w vc1 and vc2
match, summary = compare_vcards(vc1, vc2, mode='all')
print(f'match:   t{match}')
print(f'summary: t{summary}')
## Output
# match:    {'tel': True, 'email': False, 'n': True, 'version': True}
# summary:  {'abs_match': False, 'rel_match': 0.75}
## Example - A3
#  Compare ONLY COMMON USER-SPECIFIED fields b/w vc1 and vc2
match, summary = compare_vcards(vc1, vc2, fields=['email', 'n', 'tel'])
print(f'match:   t{match}')
print(f'summary: t{summary}')
## Output
# match:    {'email': False, 'n': True, 'tel': True}
# summary:  {'abs_match': False, 'rel_match': 0.6666666666666666}

代码

def get_fields(vc1, vc2, mode='common'):
if mode=='common':
fields = set(vc1.sortChildKeys()).intersection(set(vc2.sortChildKeys()))
else:
# mode = 'all'
fields = set(vc1.sortChildKeys()).union(set(vc2.sortChildKeys()))
return fields
def compare_vcards(vc1, vc2, fields=None, mode='common'):
if fields is None:
fields = get_fields(vc1, vc2, mode=mode) 
match = dict(
(field, str(vc1.getChildValue(field)).strip()==str(vc2.getChildValue(field)).strip()) 
for field in fields
)
summary = {
'abs_match': all(match.values()), 
'rel_match': sum(match.values()) / len(match)
}
return match, summary

伪数据

vcard1 = """
BEGIN:VCARD
VERSION:3.0
N;CHARSET=UTF-8:Name;;;;
TEL:0005555000
END:VCARD
"""
vcard2 = """
BEGIN:VCARD
VERSION:3.0
N;CHARSET=UTF-8:Name;;;;
TEL:0005555000
EMAIL;CHARSET=UTF-8:my_email@email.com
END:VCARD
"""
# pip install vobject
import vobject
vc1 = vobject.readOne(vcard1)
vc2 = vobject.readOne(vcard2)

参考文献

  • https://github.com/eventable/vobject
  • https://pypi.org/project/vobject/

最新更新