为什么要多次打印而不是一次?

时间:2014-09-14 23:32:11

标签: python

我有一个 \ n 分隔字符串( strings.txt )的输入列表,我试图在输入中只将每一个匹配一次文件( infilelist.tsv ),并将每一行打印到一个新文件( outfile.tsv )。

我的outfile.tsv只有infilelist.tsv打印的次数与我搜索的输入字符串的次数相同,而不是一次。我的for(for(循环不正确地只是乘以infilelist.tsv文件而不是单个匹配的行?)有什么问题?

示例脚本

#!/usr/bin/python
# gets each line containing string input

inlist = []
with open('strings.txt','r') as inlist:
    inlist = [line.strip() for line in inlist.readlines()]

tsvin = []
with open('infilelist.tsv','r') as tsvin:
    tsvin = [line.strip() for line in tsvin.readlines()]

tsvout = []
for item in inlist:
    for row in tsvin:
        tsvout.append(row)

with open('outfile.tsv', 'w') as outobj:
    outobj.writelines('\n'.join(map(str,tsvout)))

strings.txt

string1
string2
string3

infilelist.tsv

string1\tabc123\tinfo
not_important
string2\tbcd234\tinformation
unimportant
string3\tcde345\tinformacion
less_than_important

outfile.tsv

string1\tabc123\tinfo
string2\tbcd234\tinformation
string3\tcde345\tinformacion

1 个答案:

答案 0 :(得分:3)

for item in inlist:
    for row in tsvin:
        tsvout.append(row)

是双循环。 对于inlist 中的每个项目,这将遍历tsvin中的每一行。

所以这不只是迭代tsvin一次,它重复迭代len(inlist)次。


相反,您可以通过tsvin

进行单次迭代来实现目标
with open('strings.txt', 'rb') as inlist, open('infilelist.tsv', 'rb') as tsvin, open('outfile.tsv', 'wb') as outobj:
    seen = set([line.strip() for line in inlist])
    for line in tsvin:
        if line.split('\t', 1)[0] in seen:
            outobj.writelines(line)

请注意

seen = set([line.strip() for line in inlist])

正在inlist中创建一组所有行。

line.split('\t', 1)[0] in seen

将标签tsvin中的行最多拆分一次,并检查第一部分是否在集合seen中。 Checking membership in a set is O(1),同时检查列表中的成员身份是O(n)。因此,您可以通过seen set而不是list来节省一些时间。