【问题标题】:Python to compare huge text files based on multiple keysPython基于多个键比较巨大的文本文件
【发布时间】:2014-10-08 13:23:47
【问题描述】:

我有两个文本文件,每个文件大约 1GB,每行有 60 列。 每个文件中有 6 列是要比较的键。

例子:

文件 14|null|null|null|null|null|3590740374739|20077|7739662|75414741|

文件24|null|11|333|asdsd|null|3590740374739|20077|7739662|75414741|

这里两行是相等的,因为列 7、8、9 和 10 在两个文件(键)中是相同的。 我尝试了一个示例来比较文件而不考虑键,效果很好,但我需要根据键进行比较,而不是每行中的字符。

这是我在不考虑键的情况下进行比较的代码示例。

matched = open('matchedrecords.txt','w')

with open('srcone.txt') as b:
  blines = set(b)

with open('srctwo.txt') as a:
  alines = set(a)

with open('notInfirstSource.txt', 'w') as result:
  for line in alines:
    if line not in blines:
      result.write(line)
    else:
      matched.write(line)       

with open('notInsecondSource.txt', 'w') as non:
    for lin in blines:
      if lin not in alines:
        non.write(lin)

matched.close()

【问题讨论】:

  • 同一个键是否会在一个文件中出现两次(在不同的行上)?如果是这样,在这种情况下会发生什么?
  • 这里使用的基本方法是对两个文件进行排序并同时遍历它们。除了繁重的排序操作,这只是一个线性(遍历一次)函数。
  • 感谢您的评论:)。两个文件中的键组合是唯一的 @TimPietzcker。因为其中一个键是日期时间戳。

标签: python


【解决方案1】:

这是您可以根据键/列比较行的方法之一,但我不确定它的效率如何。

 matched =open('matchedrecords.txt','w')
    with open('srcone.txt') as b:
      blines = set(b)
    with open('srctwo.txt') as a:
      alines= set(a)

        # List of columns or keys to compare
        list_of_columns_to_compare=[7,8,9]

        a_columns=[]
        b_columns=[]

        for blin in blines :
           for alin in alines:
               for column_no in list_of_columns_to_compare :
                   # Appending columns  to a list to compare
                   b_columns.append(blin.split('|')[column_no])
                   a_columns.append(alin.split('|')[column_no])

                   if a_columns == b_columns:
                       matched.write(blin + " = " + alin)

【讨论】:

  • 您好@RBH 感谢您的回答:)..我尝试了 300 Mb 的数据,它需要很长时间,因为有大量的迭代。
【解决方案2】:

从 ActiveState 上的 recipe for KeyedSets 获得提示,您可以构建一个集合,然后简单地使用集合交集和集合差来产生结果:

import collections

class Set(collections.Set):
    @staticmethod
    def key(s): return tuple(s.split('|')[6:10])
    def __init__(self, it): self._dict = {self.key(s):s for s in it}
    def __len__(self): return len(self._dict)
    def __iter__(self): return self._dict.itervalues()
    def __contains__(self, value): return self.key(value) in self._dict

data = {}
for filename in 'srcone.txt', 'srctwo.txt':
    with open(filename) as f:
        data[filename] = Set(f)

with open('notInFirstSource.txt', 'w') as f:
    for lines in data['srctwo.txt'] - data['srcone.txt']:
        f.write(''.join(lines))

with open('notInSecondSource.txt', 'w') as f:
    for lines in data['srcone.txt'] - data['srctwo.txt']:
        f.write(''.join(lines))

with open('matchedrecords.txt', 'w') as f:
    for lines in data['srcone.txt'] & data['srctwo.txt']:
        f.write(''.join(lines))

【讨论】:

  • 嘿 ROb ...你能解释一下上面写的 init 函数吗。实际上要比较的唯一键不能是串行的,我的意思是它就像 ( 6,7,9,11,14)
【解决方案3】:

最后,我可以使用字典在更短的时间内实现这一目标。 即 370 MB 数据与 270 MB 数据文件相比最多 50 秒(使用元组作为键)。 这是脚本:

   reader = open("fileA",'r')
    reader2 = open("fileB",'r')
    TmpDict ={}
    TmpDict2={}
    for line in reader:
        line = line.strip()
        TmpArr=line.split('|')
       #Forming a dictionary with below columns as keys
        TmpDict[TmpArr[2],TmpArr[3],TmpArr[11],TmpArr[12],TmpArr[13],TmpArr[14]]=line
    for line in reader2:
        line = line.strip()
        TmpArr=line.split('|')
        TmpDict2[TmpArr[2],TmpArr[3],TmpArr[11],TmpArr[12],TmpArr[13],TmpArr[14]]=line
    outfile = open('MatchedRecords.txt', 'w')
    outfileNonMatchedB=open('notInB','w')
    outfileNonMatchedA=open('notInA','w')
    for k,v in TmpDict.iteritems():
        if k in TmpDict2:
            outfile.write(v+ '\n')
        else:
            outfileNonMatchedB.write(v+'\n')
    outfile.close()
    outfileNonMatchedB.close()
    for k,v in TmpDict2.iteritems():
        if k not in TmpDict:
            outfileNonMatchedA.write(v+'\n')
    outfileNonMatchedA.close()

可以对此做任何改进吗?建议我! 谢谢

【讨论】:

    猜你喜欢
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 2016-08-03
    • 2016-10-31
    • 2022-12-22
    • 1970-01-01
    • 1970-01-01
    • 2017-06-23
    相关资源
    最近更新 更多