比较 2 个输入文件的行,并输出有差异的第三个文件

Compare lines of 2 input files, and output third file with differences

我有一个功能可以让我输入两个文件文本文件,比较这些文本文件,最后创建具有差异的第三个文件。它适用于文件中的每一行,并且要使其工作,文件 1 和文件 2 中的整行文本必须相似才能注册。这是我的问题,我希望仅根据冒号后面的第一个单词来比较这些行是否相似——冒号后面的文本不需要相同。

文件结构是这样的;

文件 1 示例:

A:dog 
B:cat 
C:bird 
D:cow 
E:pig

文件 2 示例:

B:sheep
D:duck

我希望新创建的文件(文件 3)的输出包含以下内容:

A:dog
C:bird
E:pig

我希望函数仅根据分号前的第一个字符串(字母)输出文件 1 中不在文件 2 中的条目。这目前仅在文件 2 中的整行文本与文件 1 相同时有效:

def comparison(F1,F2,F3):
   with open(F1, 'r') as f:
      d=set(f.readlines())
   with open(F2, 'r') as f:
      e=set(f.readlines())
   open(F3, 'a').close()
   with open(F3, 'a') as f:
      for line in list(d-e):
         f.write(line)

comparison('file1.txt','file2.txt','file3.txt')

我主要尝试使用line.split(':')[0]来抓取冒号前的第一个字符串进行比较,但没有成功。

这是一个快速解释器会话,用于显示使用 defaultdict 的过程。我会留给你填写文件I/O。

>>> from collections import defaultdict
>>> list1 = ['a: xyz', 'b:123']
>>> list2 = ['a: dupe', 'c:456']
>>> d = defaultdict(list)
>>> for item in list1 + list2:
...     k,v = item.split(':')
...     d[k].append(v)
... 
>>> d
defaultdict(<type 'list'>, {'a': [' xyz', ' dupe'], 'c': ['456'], 'b': ['123']})
>>> ['{}:{}'.format(k,d[k][0]) for k in d if len(d[k]) == 1]
['c:456', 'b:123']

更新:文件 i/o 的示例,应请求。

from collection import defaultdict
list1 = open('file1.txt', 'r').readlines()
list2 = open('file2.txt', 'r').readlines()
d = defaultdict(list)
for item in list1 + list2:
    k,v = item.split(':')
    d[k].append(v)
with open('file3.txt', 'a') as output:
    output.writelines(['{}:{}\n'.format(k,d[k][0]) for k in d if len(d[k]) == 1])

解压最后一行的英文,意思是:

  • 遍历 d(我们的字典)中的键
  • 忽略我们为该键添加了多个项目的项目 (非唯一键)
  • 对于我们没有忽略的每个项目(是唯一的),格式化键和 值返回到 'k:v' 字符串并添加换行符
  • 对于重新组合的字符串集合(加上换行符),写下 整个事情都归结为我们的档案。

使用应将文件置于 CSV 格式。所以只需将它们放入 excel 并将其保存为 CSV。

之后做这个。

f = open('file1.csv')
csv_f = csv.reader(f)
animals1 = []

for row in csv_f:
    animals1.append(row[0])   #[] put number in there. 0 = first Column 
f.close()

f = open('file2.csv')
csv_f = csv.reader(f)
animals2 = []

for row in csv_f:
    animals2.append(row[0])      
f.close()


animals1 = set(animals1)
animals2 = set(animals2)

print animals1.difference(aniamls2)

所以这段代码基本上是读取您的 csv 文件,并打印出差异。 您可以实现它并将其写入新文件。

编辑:请注意,根据对此答案的评论:此方法不是解决此问题的最佳方法。但它似乎确实回答了用户根据他的进一步评论提出的问题...

OP 要求 "simpler" 无需字典即可完成此操作。这可以通过读取每个文件的所有行然后仅获取每行的第一个字母来完成。然后根据 file2 中的字母数组过滤数据。这将非常依赖于文本文件的特定格式,以及 file1 被 file2 过滤而不是相反的事实。但是,就是说,执行此操作的 python 应该看起来像这样(行号来自我的文本编辑器,而不是代码的一部分):

1 f=open("./file1.txt","r")
2 data1=f.readlines()
3 letter1=[]
4 f.close()
5 
6 g=open("./file2.txt","r")
7 data2=g.readlines()
8 letter2=[]
9 g.close()
10 
11 #just take the first character (the 'A', 'B', etc)
12 for dat in data1:
13     letter1.append(dat[0]) 
14 for dat in data2:
15     letter2.append(dat[0])
16 
17 h=open("output.txt","w")
18 for dat in data1:
19     if dat[0] not in letter2:
20         h.write(dat)
21 
22 h.close()

嗯,有很多方法可以实现您的 objective。实际上你非常接近。使用集合来处理值的想法是评估每个文件中两个列表之间差异的好方法。但是,您需要将冒号之前的值与冒号之后的值分开,否则您将比较整行,这在您的情况下是错误的。获得差异后,您将需要根据差异检索两个文件中的整行,以将它们写入新文件。

所以,一个解决方案的想法是:当你读取一个文件时,你将每一行保存在一个字典中,以便将来可以检索它,并且将冒号之前的值保存在一个集合中(一个集合对于每个文件)评估值的差异(就像你已经做的那样)。

实际上这意味着:

d = {}  # Our dictionary to store the lines
a = set()  # a set for the first file
b = set()  # a set for the second file

with open('file1') as fp:
    for line in fp:
        key, value = line.split(':')  # this separate the values in each line
        d[key] = value.strip()  # add one line to the dictionary
        a.add(key)  # save just the value from the colon left

然后,您需要与第二个文件相同。也许您会将其作为一个函数来使您的代码更稳定且更易于维护。

之后,您将拥有一本完整的词典。因为你不想写重复的值,所以我们的代码覆盖一些值是可以的。

现在,您需要评估差异。你这样做的方式很好。但是,如果您知道第一个文件比第二个文件具有更多的值,并且可能还有其他问题,它就会起作用。您将需要查看设置方法以正确实现此目的(提示:并集和交集),但让我们按照您的方式进行操作:

diff = a - b

最后,根据我们的不同,写下从字典中检索出来的结果:

with open('results', 'w') as fp:
    for key in diff:  # you can use sorted(diff) instead just diff here
        fp.write("{0}:{1}\n".format(key, d[key]))

当然,这种方式不是更pythonic的方式,但它是某种直截了当的方式。其他答案可能比这个简单。