Python 如何根据给定列表中的单词合并两个csv文件?
我有两个csv文件,每个都是这种格式Python 如何根据给定列表中的单词合并两个csv文件?,python,loops,csv,for-loop,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
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文件中,那么我们应该将其与zip和分数一起包含在新的csv文件中。否则我们应该在里面打印“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
即使有很多常用词,最终合并的csv文件中也只会打印“x”。我认为问题在于循环。但是,我似乎没有弄明白问题所在 首先,第一次调用
list(readerX)
将耗尽迭代器,迭代器是文件句柄
其次,rev
应该已经是名称
,因此检查是否包含以下等式:如果name==rev
第三,除了每个文件中的姓氏之外,您通常会得到'x',因为您将文件迭代到最后,只有最后一行才真正重要。您应该在找到名称后立即中断内部循环,但只有在迭代整个文件而未找到名称后才设置默认值
此外,重复迭代这两个文件是非常糟糕的性能。您最好将这两个文件加载到一个永久性的数据结构中,以更快的速度查找,就像使用名称作为键的嵌套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'
#下一步(reader1)#必要时跳过标题行
lst1=list(reader1)#预先将所有数据加载到列表中。。。
对于lista中的我:
对于lst1中的行:#。。。可以重复迭代的
rev=第[1]行
如果i==rev:#比较是否相等
分数=第[2]行
zip=行[0]
break#首先,第一次调用list(readerX)
将耗尽迭代器,即文件句柄
其次,rev
应该已经是名称
,因此检查是否包含以下等式:如果name==rev
第三,除了每个文件中的姓氏之外,您通常会得到'x',因为您将文件迭代到最后,只有最后一行才真正重要。您应该在找到名称后立即中断内部循环,但只有在迭代整个文件而未找到名称后才设置默认值
此外,重复迭代这两个文件是非常糟糕的性能。您最好将这两个文件加载到一个永久性的数据结构中,以更快的速度查找,就像使用名称作为键的嵌套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'
#下一步(reader1)#必要时跳过标题行
lst1=list(reader1)#预先将所有数据加载到列表中。。。
对于lista中的我:
对于lst1中的行:#。。。可以重复迭代的
rev=第[1]行
如果i==rev:#比较是否相等
分数=第[2]行
zip=行[0]
break#您不认为最好将这两个文件读入一个嵌套字典,其中名称是键,值是带有键“zip”、“zip1”、“score”和“score1”的字典吗
{'hary' :
{'zip1':33478,
'zip':33441 ,
'score':23,
'score1':23 }
}
然后在列表中迭代并打印“x”,无论键是否存在,您不认为最好将这两个文件读入一个嵌套字典,其中名称为键,值为带有键“zip”、“zip1”、“score”和“score1”的字典吗
{'hary' :
{'zip1':33478,
'zip':33441 ,
'score':23,
'score1':23 }
}
然后在列表中迭代并打印“x”,以查找任何不存在的键上述代码中的错误:
列表的第一个循环(reader1)耗尽迭代器,迭代器是文件句柄。因此,当“lista”的下一次迭代开始时,reader1为空,len=0。
将数据存储在列表或字典中,而不是重复迭代文件句柄
当i与rev匹配时,如果(i在rev中),您继续迭代文件的其余部分,这会导致zip和score的值重置为“x”,因为下一次迭代“i在rev中”将给出False。您需要拆下else零件以更正此问题。相反,在lista中i的后面声明zip,并将其得分为“x”:
上述代码中的错误:
列表的第一个循环(reader1)耗尽迭代器,迭代器是文件句柄。因此,当“lista”的下一次迭代开始时,reader1为空,len=0。
将数据存储在列表或字典中,而不是重复迭代文件句柄
当i与rev匹配时,如果(i在rev中),您继续迭代文件的其余部分,这会导致zip和score的值重置为“x”,因为下一次迭代“i在rev中”将给出False。您需要拆下else零件以更正此问题。相反,在lista中i的后面声明zip,并将其得分为“x”:
谢谢另外,请您指出我上面代码中的错误(除了呼叫列表(readerX))好吗?这样我就可以从错误中吸取教训,不再重蹈覆辙。谢谢你的及时回复。我还通过使用if I==rev
尝试了该代码,但输出没有改变(整个文件都打印了x)。请允许我再问一个问题,我想我的问题的关键是在这句话中,如果两个文件中都没有名字,那么上一次迭代中的zip和score变量不会改变,并且会再次写入。。。我应该如何实施它?对不起,我刚开始学习python不久。谢谢!另外,请您指出我上面代码中的错误(除了呼叫列表(readerX))好吗?这样我才能从错误中吸取教训,不再重蹈覆辙。谢谢你的及时提醒