2

我有两个文本文件(A 和 B),如下所示:

A:
1 stringhere 5
1 stringhere 3
...
2 stringhere 4
2 stringhere 4
...

B:
1 stringhere 4
1 stringhere 5
...
2 stringhere 1
2 stringhere 2
...

我要做的是阅读这两个文件,而不是像这样的新文本文件:

1 stringhere 5
1 stringhere 3
...
1 stringhere 4
1 stringhere 5
...
2 stringhere 4
2 stringhere 4
...
2 stringhere 1
2 stringhere 2
...

使用 for 循环,我创建了函数(使用 Python):

def find(arch, i):
    l = arch   
    for line in l:
        lines = line.split('\t')
        if i == int(lines[0]):
           write on the text file
        else:            
            break

然后我这样调用函数:

for i in range(1,3):        
    find(o, i)
    find(r, i)  

发生的情况是我丢失了一些数据,因为读取了包含不同数字的第一行,但它不在最终的 .txt 文件中。在此示例中,2 stringhere 4 和 2stringhere 1 丢失。

有没有办法避免这种情况?

提前致谢。

4

3 回答 3

2

可能有一种不太复杂的方法来实现这一点。以下内容还按照它们在文件中出现的顺序保留这些行,就像您想要做的那样。

lines = []
lines.extend(open('file_a.txt').readlines())
lines.extend(open('file_b.txt').readlines())
lines = [line.strip('\n') + '\n' for line in lines]
key = lambda line: int(line.split()[0])
open('out_file.txt', 'w').writelines(sorted(lines, key=key))

前三行将输入文件读入单个行数组。

第四行确保每一行的末尾都有一个换行符。如果您确定两个文件都以换行符结尾,则可以省略此行。

第五行将用于排序的键定义为字符串第一个单词的整数版本。

第六行对行进行排序并将结果写入输出文件。

于 2013-11-10T16:09:46.660 回答
2

在您的循环中,当该行的开头与i您中断的值不同时,但您已经消耗了一行,因此当第二次使用 调用该函数时i+1,它从第二个有效行开始。

预先读取内存中的整个文件(请参阅@JFSebastian 的回答),或者,如果这不是一个选项,请将您的函数替换为以下内容:

def find(arch, i):
    l = arch
    while True:
        line=l.readline()
        lines = line.split('\t')
        if line != "" and i == int(lines[0]): # Need to catch end of file
            print " ".join(lines),
        else:
            l.seek(-len(line), 1) # Need to 'unread' the last read line
            break

此版本“倒回”光标,以便下一次调用readline再次读取正确的行。请注意,不鼓励将隐式for line in lseek调用混合,因此while True.

示例:

$ cat t.py
o = open("t1")
r = open("t2")
print o
print r


def find(arch, i):
    l = arch
    while True:
        line=l.readline()
        lines = line.split(' ')
        if line != "" and i == int(lines[0]):
            print " ".join(lines),
        else:
            l.seek(-len(line), 1)
            break

for i in range(1, 3):
    find(o, i)
    find(r, i)

$ cat t1 
1 stringhere 1
1 stringhere 2
1 stringhere 3
2 stringhere 1
2 stringhere 2
$ cat t2
1 stringhere 4
1 stringhere 5
2 stringhere 1
2 stringhere 2
$ python t.py
<open file 't1', mode 'r' at 0x100261e40>
<open file 't2', mode 'r' at 0x100261ed0>
1 stringhere 1
1 stringhere 2
1 stringhere 3
1 stringhere 4
1 stringhere 5
2 stringhere 1
2 stringhere 2
2 stringhere 1
2 stringhere 2
$ 
于 2013-11-10T15:41:10.733 回答
2

如果文件适合内存:

with open('A') as file1, open('B') as file2:
     L = file1.read().splitlines() 
     L.extend(file2.read().splitlines()) 
L.sort(key=lambda line: int(line.partition(' ')[0])) # sort by 1st column
print("\n".join(L)) # print result

如果总行数低于一百万,这是一种有效的方法。否则,特别是如果您有许多已排序的文件;你可以heapq.merge()用来组合它们

于 2013-11-10T15:24:35.563 回答