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

时间:2015-02-02 15:36:21

标签: python file function compare output

我有一个功能工作,允许我输入两个文件文本文件,比较这些文本文件,最后创建一个差异的第三个文件。它适用于文件中的每一行,并且为了使其工作,整个文本行必须在文件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]来获取冒号之前的第一个字符串进行比较,但是还没有成功。

4 个答案:

答案 0 :(得分:1)

这是一个使用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(我们的字典)
  • 中的键
  • 忽略我们为该密钥添加多个项目的项目 (非唯一密钥)
  • 对于我们不忽略的每个项目(唯一),格式化密钥和 价值回到&#39; v&#39;字符串并添加换行符
  • 对于重新组装的字符串集合(加上换行符),请写下 整件事直到我们的档案。

答案 1 :(得分:1)

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

因此,解决方案的一个想法是:当您正在读取一个文件时,将每行保存在字典中以使其在将来可检索,并且还将值保存在集合中的冒号之前(每个集合中的值) file)来评估值的差异(正如你已经做过的那样)。

实际上它意味着:

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

然后,您需要与第二个文件相同。也许你会把它作为一个功能,让你的代码变得更容易维护。

在此之后,您将拥有一本完整的字典。由于您不想写重复值,因此我们的代码可以覆盖某些值。

现在,您需要评估差异。你这样做的方式很好。但是,如果您知道第一个文件的值多于第二个文件,也可能是其他问题,那么它就可以正常工作。你需要看看set方法才能正确实现这一点(提示:联合和交叉点),但让我们按你的方式做:

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的方式,但它是一种直截了当的方式。其他答案可能比这个更简单。

答案 2 :(得分:0)

使用时应将文件格式化为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文件,并打印出差异。 你可以实现它并将其写入一个新文件。

答案 3 :(得分:0)

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

OP要求在没有词典的情况下采用“更简单”的方式。这可以通过读取每个文件的所有行然后获得每行的第一个字母来完成。然后根据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()