#!/usr/bin/env python2.7
import vobject
abinfile='/foo/bar/dir/infile.vcf' #ab stands for address book
aboutfile='/foo/bar/dir/outfile.vcf'
def eliminate_vcard_duplicates (abinfile, aboutfile):
#we first convert the Adrees Book IN FILE into a list
with open(abinfile) as source_file:
ablist = list(vobject.readComponents(source_file))
#then add each vcard from that list in a new list unless it's already there
ablist_norepeats=[]
ablist_norepeats.append(ablist[0])
for i in range(1, len(ablist)):
jay=len(ablist_norepeats)
for j in reversed(range(0, jay)): #we do reversed because usually cards have duplicates nearby
if ablist_norepeats[j].serialize() == ablist[i].serialize():
break
else:
jay += -1
if jay == 0:
ablist_norepeats.append(ablist[i])
#and finally write the singularized list to the Adrees Book OUT FILE
with open(aboutfile, 'w') as destination_file:
for j in range(0, len(ablist_norepeats)):
destination_file.write(ablist_norepeats[j].serialize)
eliminate_vcard_duplicates(abinfile, aboutfile)
上面的代码有效并创建了一个新文件,其中没有完全相同的重复项(具有相同单数化的重复项)。我知道代码有一些效率问题:它是 n 平方,当它可能是 n*log n 时;我们只能将每个 vacard 序列化一次;for 等的使用效率低下。在这里,我想提供一个简短的代码来说明我不知道如何解决的一个问题。
我不知道如何优雅地解决这个问题:如果卡片中的某些字段被打乱,它不会检测到它们是否相等。有没有办法使用 vobject、re 或其他方法检测此类重复项?
测试中使用的文件内容,有四个相同的电子名片(电话乱码乱码 - 不是电子邮件乱码的想法),是这个:
BEGIN:VCARD
VERSION:3.0
FN:Foo_bar1
N:;Foo_bar1;;;
EMAIL;TYPE=INTERNET:foobar1@foo.bar.com
TEL;TYPE=CELL:123456789
TEL;TYPE=CELL:987654321
END:VCARD
BEGIN:VCARD
VERSION:3.0
FN:Foo_bar1
N:;Foo_bar1;;;
EMAIL;TYPE=INTERNET:foobar1@foo.bar.com
TEL;TYPE=CELL:123456789
TEL;TYPE=CELL:987654321
END:VCARD
BEGIN:VCARD
VERSION:3.0
FN:Foo_bar1
N:;Foo_bar1;;;
TEL;TYPE=CELL:123456789
TEL;TYPE=CELL:987654321
EMAIL;TYPE=INTERNET:foobar1@foo.bar.com
END:VCARD
BEGIN:VCARD
VERSION:3.0
FN:Foo_bar1
N:;Foo_bar1;;;
TEL;TYPE=CELL:987654321
TEL;TYPE=CELL:123456789
EMAIL;TYPE=INTERNET:foobar1@foo.bar.com
END:VCARD
上面的代码不会检测到这四个都是一样的,因为最后一个的电话号码被打乱了。
作为奖励积分,如果有人有更快的算法,如果可以共享它会很棒。上述一个需要几天时间才能处理一个 30.000 Vcard 文件......