【问题标题】:Optimize python file comparison script优化python文件比较脚本
【发布时间】:2012-03-29 19:37:52
【问题描述】:

我编写了一个有效的脚本,但我猜这不是最有效的。我需要做的是:

  • 比较两个包含用户信息的 csv 文件。它本质上是一个成员列表,其中一个文件是另一个文件的更新版本。
  • 文件包含ID、姓名、状态等数据
  • 仅将新文件中旧文件中不存在或包含更新信息的记录写入第三个 csv 文件。对于每条记录,都有一个唯一的 ID,可以让我确定记录是新的还是以前存在的。

这是我目前写的代码:

import csv

fileAin = open('old.csv','rb')
fOld = csv.reader(fileAin)

fileBin = open('new.csv','rb')
fNew = csv.reader(fileBin)

fileCout = open('NewAndUpdated.csv','wb')
fNewUpdate = csv.writer(fileCout)

old = []
new = []

for row in fOld:
    old.append(row)
for row in fNew:
    new.append(row)

output = []

x = len(new)
i = 0
num = 0

while i < x:
    if new[num] not in old:
        fNewUpdate.writerow(new[num])

    num += 1
    i += 1

fileAin.close()
fileBin.close()
fileCout.close()

就功能而言,此脚本有效。但是,我试图在包含数十万条记录的文件上运行它,并且需要几个小时才能完成。我猜问题在于将两个文件都读取到列表并将整行数据视为单个字符串进行比较。

我的问题是,我正在尝试做的事情是否有一种更快、更有效的方法来处理这两个文件以创建仅包含新记录和更新记录的第三个文件?我真的没有目标时间,只是想了解 Python 中是否有更好的方法来处理这些文件。

提前感谢您的帮助。

更新以包含示例数据行:

123456789,34,DOE,JOHN,1764756,1234 MAIN ST.,CITY,STATE,305,1,A

【问题讨论】:

  • 顺便说一句:既然您使用的是 2.7,为什么不使用上下文管理器打开文件呢?这样,即使出现错误,它们也会被关闭,而无需您编写 try: ... except IOError: ... python.org/dev/peps/pep-0343
  • 你能给我们提供一个示例数据行吗?
  • 那是因为我对 Python 还是很陌生。我选择它更多是出于工作的需要。我需要做的很多事情都很简单,只需要重复多次。我不熟悉您提到的上下文管理器,但感谢您提供链接。我会检查一下并了解更多信息。谢谢!
  • 主帖子中包含的示例数据行。
  • 第一个值是唯一ID吗?

标签: python algorithm optimization csv complexity-theory


【解决方案1】:

这样的事情怎么样?代码最大的低效之一是每次都检查 new[num] 是否为 old,因为 old 是一个列表,因此您必须遍历整个列表。使用字典要快得多。

import csv

fileAin = open('old.csv','rb')
fOld = csv.reader(fileAin)

fileBin = open('new.csv','rb')
fNew = csv.reader(fileBin)

fileCout = open('NewAndUpdated.csv','wb')
fNewUpdate = csv.writer(fileCout)

old = {row[0]:row[1:] for row in fOld}
new = {row[0]:row[1:] for row in fNew}
fileAin.close()
fileBin.close()

output = {}

for row_id in new:
    if row_id not in old or not old[row_id] == new[row_id]:
        output[row_id] = new[row_id]

for row_id in output:
    fNewUpdate.writerow([row_id] + output[row_id])


fileCout.close()

【讨论】:

  • 这当然可以非常快地处理文件。但是,我预期的输出文件包含整个 New.csv 文件。我会修改这个脚本,看看我是否可以让它只写新的或更新的记录。感谢您的先机。
  • 新旧的列数是否完全相同?我的代码做出了这样的假设。
  • 是的,新旧的列数相同。使用我的示例行我会寻找这样的东西:旧的:123456789,34,DOE,JOHN,1764756,1234 MAIN ST.,CITY,STATE,305,1,A new: 123456789,32,DOE,JOHN,1764756 ,1234 MAIN ST.,CITY,STATE,305,1,A 唯一改变的是在第二列中,值从 34 变为 32。在这种情况下,我需要将该记录复制到输出文件中,以及任何全新的记录。
  • 我认为if not all(old_col == new_col for old_col in old[row_id] for new_col in new[row_id])这行是错误的;这不会成对比较元素,它会检查笛卡尔积。可能if not old[row_id] == new[row_id]: 就足够了。
  • 测试集合和字典中的成员关系非常快:它们使用散列(这就是为什么集合中的成员和字典中的键需要是可散列的)。要确定字典中是否有某些内容,请检查索引,然后查看页面。 (非常粗略。)相比之下,要像您一样测试列表中的成员资格,您必须逐个阅读元素。对于不存在的元素,除非您通读所有元素,否则您不会知道它们不存在。
【解决方案2】:

【讨论】:

    【解决方案3】:

    按您的唯一字段对数据进行排序,然后使用类似于归并排序的合并步骤的比较过程:

    http://en.wikipedia.org/wiki/Merge_sort

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-22
      • 1970-01-01
      • 1970-01-01
      • 2021-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-10
      相关资源
      最近更新 更多