如何根据给定列表中的单词合并两个csv文件?

时间:2017-12-04 05:28:10

标签: python loops csv for-loop

我有两个csv文件,每个都是这种格式,

file1
zip     name    score                
23431   david   12                  
23231   rob     45
33441   hary    23
98901   rgrg    55  


file2
zip1    name1   score1                
23433   david   12                  
23245   stel    45
33478   hary    23
98988   rob     55  
12121   jass    33

我有一个名字的列表,比如这个

lista = ['harry', 'rob', 'wine', 'david', 'jass']

最终的csv文件应如下所示:

name    zip     score       zip1     score1
harry   x       x           x           x
rob     23231   45          98988       55
wine    x       x           x           x
david   23431   12          23433       12
jass    x       x           12121       33

这意味着,如果列表中的任何名称位于任何一个csv文件中,那么我们应该将它包含在新的csv文件中,以及它的zip和score。否则我们应该在其中打印'x'。

这是我到目前为止所做的:

import csv
with open('file1.csv', 'r') as input1, open('file2.csv', 'r') as input2, open('merge_final.csv', 'w') as output:
    writer = csv.writer(output)
    reader1 = csv.reader(input1)
    eader2 = csv.reader(input2)

    lista = ['harry', 'rob', 'wine', 'david', 'jass']
    writer.writerow(['name','zip','score','zip1','score'])

        for i in lista:     
            for row in list(reader1):
                rev = row[1]
                if i in rev:
                    score = row[2]
                    zip = row[0]    
                else:
                    score = 'x'
                    zip = 'x'               
            for row in list(reader2):
                rev = row[1]
                if i in rev:
                    score1 = row[2]
                    zip1 = row[0]
                else:
                    score1 = 'x'
                    zip1 = 'x'  
            writer.writerow([i, score, zip, score1, zip1])

此代码未按预期工作。这是我使用此代码获得的输出。

name    zip     score       zip1     score1
harry   x       x           x           x
rob     x      x            x            x
wine    x       x           x           x
david   x       x           x           x
jass    x       x           x           x

即使认为有许多常用词,只有'x'会在最终合并的csv文件中打印出来。我认为问题在于循环。但是,我似乎没有弄清楚这个问题。

3 个答案:

答案 0 :(得分:3)

首先,list(readerX)的第一次调用耗尽了作为文件句柄的迭代器。

其次,rev应该已经是name,因此检查相等性不包含:if name == rev

第三,除了每个文件中的姓氏之外,你大多得到'x',因为你将文件迭代到最后,只有最后一行才真正重要。只要找到名称,就应该break内部循环,但只有在迭代整个文件找不到名称后才能设置默认值。< / p>

此外,重复迭代这两个文件在性能方面也是非常糟糕的。您最好将这两个文件加载到永久数据结构中,使用更快的查找,如名称为键的嵌套dict

d1 = {row[1]: {'zip': row[0], 'score': row[2]} for row in reader1}
d2 = {row[1]: {'zip': row[0], 'score': row[2]} for row in reader2}
#   {'david': {'zip': 23431, 'score: 12, ...}    

for name in lista:
    if name in d1 or name in d2:
        writer.writerow([
            name,
            d1.get(name, {}).get('zip', 'x'),
            d1.get(name, {}).get('score', 'x'),
            d2.get(name, {}).get('zip', 'x'),
            d2.get(name, {}).get('score', 'x'),
        ])

要使自己的方法有效,请按以下步骤进行更改,但请注意,由于嵌套循环,这对于较大的数据而言性能非常糟糕:

# next(reader1)  # skip the header line if necessary
lst1 = list(reader1)  # load all the data into a list beforehand ...
for i in lista:  
    for row in lst1:  # ... that you can repeatedly iterate
        rev = row[1]
        if i == rev:  # compare for equality
            score = row[2]
            zip = row[0]   
            break  # <- you found the name, so end the loop! 
    else:  # note the indentation: this is a for-else-loop, not an if-else
        # the else-part is only executed if the for loop was NOT break'ed
        score = 'x'
        zip = 'x'  

答案 1 :(得分:0)

你认为将这两个文件读入一个嵌套字典会更好,其中名称是键,值是带字符串的字典&#39; zip,&#39; zip1& #39;,&#39;得分&#39;和&#39;得分1&#39;?

    {'hary' : 
        {'zip1':33478, 
         'zip':33441 ,
         'score':23,
         'score1':23 }
    }

然后遍历列表并打印&#39; x&#39;无论钥匙不存在

答案 2 :(得分:0)

上述代码中的错误:

  1. list的第一个循环(reader1)耗尽了作为文件句柄的迭代器。因此,当下一次迭代时,列表&#39;启动reader1为空,len = 0 而不是重复迭代文件句柄存储列表或字典中的数据。
  2. 如果i与if匹配,则if(i in rev)你继续迭代文件的其余部分,这会导致zip和得分的值被重置为&#39; x&#39;至于下一次迭代&#34;我在rev&#34;会给出错误的。你需要删除else部分来纠正这个问题。而是声明zip,得分为&#39; x&#39;就在我的lista之后: