2014-01-21 86 views
2

我在Python中格式化CSV以获得所需的结果,但我的代码似乎不能正常工作。在Python中比较两个CSV

我有格式的第一个CSV文件:在格式

2,a 
1,a 
4,a 
5,a 
3,a 
1,a 
3,b 
2,b 
1,a 

第二CSV文件:

1,a,123 
1,a,234 
2,a,456 
2,b,345 
3,a,789 
3,b,232 
4,a,987 

作为第一个CSV文件没有排序,第二CSV文件排序中相对于第一列递增顺序

我想输出格式:

2,a,456 
1,a,123 
4,a,987 
5,a 
3,a,789 
1,a,234 
3,b,232 
2,b,345 
1,a 

结果印在相对于第一CSV,如果第一CSV文件组合未在第二CSV文件中发现,例如,如果5,a不在第二CSV文件,然后只是5,a被印刷在其推崇位置。第一个CSV文件包含许多重复项,而第二个CSV文件中的每一行都是唯一的。

这里是我的代码

for (num,alpha) in first_csv: 
    value_found = True 
    for (num1,alpha1,num2) in second_csv: 
     if (num == num1 and alpha == alpha1): 
      csv_out += str(num) + ',' + str(alpha) + ',' + str(number) 
      value_found = False 
    if value_found: 
     count+=1 
     if count == 1: 
      csv_out += str(num) + ',' + str(alpha) 

first_csv和second_csv的元组读取的代码的CSV文件后,我已经创建了:

with open('first_csv.csv') as f: 
    f.readline() 
    first_csv = tuple(csv.reader(f, delimiter=',')) 


with open('second_csv.csv') as f: 
    f.readline() 
    second_csv = tuple(csv.reader(f, delimiter=',')) 

但它不是打印所需的输出,我在哪里我做错了?

+0

您是否考虑过使用SQLite将数据存储到两个表中,然后在这两个表上执行联接操作以获得所需的结果?试图单独将它与Python联合起来会很快变得痛苦。 – Makoto

+0

@makoto你有查询可以做到这一点,我不擅长数据库。 – user3218088

+0

该示例指示第二个文件中的每个匹配仅使用一次 - 第三个“1,a”不匹配任何内容。你能否更详细地讨论这个要求? –

回答

3

此收集来自第二文件中的num2值成deque秒的字典。当找到匹配项时,将使用deque.popleft删除它们,以便按照与第二个文件中出现的顺序相同的顺序每次仅使用一次匹配项。

from collections import defaultdict, deque 

with open('second_csv.csv') as f: 
    next(f) #skip header 
    dic = defaultdict(deque) 
    for num1,alpha1,num2 in csv.reader(f, delimiter=','): 
     dic[num1, alpha1].append(num2) 

with open('first_csv.csv') as f, open('out.csv', 'wb') as fout: 
    next(f) #skip header 
    csv_out = csv.writer(fout) 
    for num,alpha in csv.reader(f, delimiter=','): 
     try: 
      num2 = dic[num,alpha].popleft() 
      csv_out.writerow([num,alpha,num2]) 
     except IndexError: 
      csv_out.writerow([num,alpha]) 
  • 一个deque保留您通过append添加和删除popleft项目的顺序。
  • 一个dict确实通过键快速查找它可以是一个元组
  • 一个defaultdict(deque)dict当你访问一个缺少键,可以自动创建一个空deque,直接让你可以append它。
+0

谢谢,我知道这将需要一些你的时间,我是新的stackoverflow,所以我没有积分upvote你的答案,我这是我第一次看到你用过的东西,你可以吗请摆脱一些光线,让我知道我做错了什么。再次非常感谢。 – user3218088

+0

@ user3218088你的方法中的主要问题是你不跟踪匹配。使用元组来保存'second_csv'使得查找不必要地困难,并且不允许你删除匹配。 –

2

这应该有所斩获。请注意,对于first_csv上的每次迭代,最糟糕的情况是它必须迭代到第二个csv文件中数据的剩余部分的末尾(如果匹配,行将被弹出)。

import csv 

with open("second_csv.csv") as in_file: 
    reader = csv.reader(in_file) 
    lookup = list(reader) 

with open("first_csv.csv") as in_file, open('output.csv', 'wb') as out_file: 
    reader = csv.reader(in_file) 
    writer = csv.writer(out_file) 
    for row in reader: 
     for i, data in enumerate(lookup): 
      if row == data[:2]: 
       row = lookup.pop(i) 
       break 
     writer.writerow(row) 

output.csv

2,a,456 
1,a,123 
4,a,987 
5,a 
3,a,789 
1,a,234 
3,b,232 
2,b,345 
1,a 
+0

谢谢Steinar:这也适用。没有声望,以upvote你的答案,对不起队友。 – user3218088