从列表更新列表的算法
我有一个数据源,它提供了一些对象及其属性的列表(是个CSV文件,但这不重要)。每次我的程序运行时,都需要获取一份新的对象列表,把它和数据库中存储的对象(及其属性)进行比较,然后根据需要更新数据库。
处理新对象很简单——数据源给每个对象分配一个顺序的ID号码,只需检查新信息中的最高ID号码和数据库中的最高ID号码就可以了,问题就解决了。不过,我想要一些建议,针对其他情况,比如某个对象的属性发生了变化,或者某个对象被删除了。
一个简单的解决办法是从数据库中提取所有对象,然后找出两个列表(旧的和新的)之间的差异,再检查这些结果,但这样做在数据量大的时候似乎效率不高。有没有什么好的主意?
4 个回答
你需要在数据库和CSV文件中都有时间戳。时间戳应该显示记录最后一次更新的时间,你需要比较同一ID的记录的时间戳,以决定是否需要更新它。
关于你提到的交集想法……其实应该反过来做!你需要先把CSV中的所有数据导入到一个临时表中,然后再在两个SQL数据库表之间进行交集操作。如果你使用的是Oracle或者MS SQL 2008(不确定2005是否也可以),你会发现一个非常有用的MERGE关键字,这样你就可以用更少的精力写SQL,而不是在其他编程语言中合并数据。
难道就没有办法保持一个“最后修改时间”的字段吗?听起来你真正想要的就是这个:根据上次备份的时间,来做增量备份,也就是只备份那些在上次备份后被修改、删除或添加的内容。
处理大量数据的标准方法大致是这样的。
我们假设 list_1 是“主列表”(没有重复项),而 list_2 是“更新列表”,可能会有重复项。
iter_1 = iter( sorted(list_1) ) # Essentially SELECT...ORDER BY
iter_2 = iter( sorted(list_2) )
eof_1 = False
eof_2 = False
try:
item_1 = iter_1.next()
except StopIteration:
eof_1= True
try:
item_2 = iter_2.next()
except StopIteration:
eof_2= True
while not eof_1 and not eof_2:
if item_1 == item_2:
# do your update to create the new master list.
try:
item_2 = iter_2.next()
except StopIteration:
eof_2= True
elif item_1 < item_2:
try:
item_1 = iter_1.next()
except StopIteration:
eof_1= True
elif item_2 < item_1:
# Do your insert to create the new master list.
try:
item_2 = iter_2.next()
except StopIteration:
eof_2= True
assert eof_1 or eof_2
if eof_1:
# item_2 and the rest of list_2 are inserts.
elif eof_2:
pass
else:
raise Error("What!?!?")
是的,这个过程可能需要排序。如果你在把 list_1 写回文件时保持它的顺序,这样可以节省很多时间。如果 list_2 能够以一种保持排序的方式来累积,那也能节省不少时间。
抱歉说得有点啰嗦,但你需要知道是哪个迭代器引发了 StopIteration
,所以你不能简单地把整个 while 循环放在一个大的 try 块里。