【问题标题】:Algorithm for updating a list from a list从列表更新列表的算法
【发布时间】:2009-06-19 18:09:22
【问题描述】:
我有一个提供对象列表及其属性的数据源(一个 CSV 文件,但这没关系)。每次我的程序运行时,它都需要提取对象列表的新副本,将其与存储在数据库中的对象列表(及其属性)进行比较,并根据需要更新数据库。
处理新对象很容易 - 数据源为每个对象提供了一个连续的 ID 号,对照数据库检查新信息中的顶部 ID 号,就大功告成了。我正在寻找其他情况的建议 - 对象的某些属性已更改,或者对象已被删除。
一个天真的解决方案是从数据库中提取所有对象并获取两组(旧的和新的)交集的补集,然后检查这些结果,但如果集合变大。有什么想法吗?
【问题讨论】:
标签:
python
google-app-engine
set
【解决方案1】:
处理大量数据的标准方法就是这样。
我们假设 list_1 是“master”(没有重复项),而 list_2 是可能有重复项的“updates”。
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 块中。
【解决方案2】:
有没有办法维护“上次修改时间”字段?这就是您真正想要的:增量备份,基于上次运行备份的时间,与上次更改/删除(/添加)对象的时间相比。
【解决方案3】:
您的数据库和 CSV 文件中都需要有时间戳。时间戳应该显示记录更新时的数据,您应该比较具有相同 ID 的记录的时间戳来决定是否需要更新它
关于你对交叉路口的想法......
反之亦然!
您必须将所有数据从 CSV 导入临时表,并在 2 个 SQL 数据库表之间进行交集。如果您使用 Oracle 或 MS SQL 2008(不确定是否为 2005),您会发现一个非常有用的 MERGE 关键字,因此您可以更轻松地编写 SQL,然后您将花费在其他编程语言中合并数据。
【解决方案4】:
当您将列表拉入您的程序时,迭代该列表以执行基于数据库表中的列属性的查询,该属性映射到列表中对象的相同属性,例如 ObjectName。或者您可以将整个表格加载到列表中并以这种方式比较列表。我假设您对除了数据库分配的 ID 之外存在的对象有一些独特的东西。
如果通过查询在表中未找到该对象,则创建一个新条目。如果像提到的 FogleBird 那样找到它,则在表中存储该对象的计算哈希或 CRC,您可以将其与列表中的对象进行比较(在对象上运行计算)。如果哈希值不匹配,请使用列表中的对象更新该对象。