Python 连接/合并一次文件中的一行



我愿意逐行连接两个文件,以便每个文件的每一行都连续合并到第三个文件中。

所以我有以下代码和以下文本文件:

file1.txt
1
3
5
7
file2.txt
2
4
6

法典:

from ast import literal_eval
def merge_lines():
with open("file1.txt") as f1, open("file2.txt") as f2:
with open("file3.txt", "r+") as tfile:
f1_lists = (literal_eval(line) for line in f1)
f2_lists = (literal_eval(line) for line in f2)
for l1, l2 in zip(f1_lists, f2_lists):
tfile.write(str(l1))
tfile.write("n")
tfile.write(str(l2))
tfile.write("n")
combine_hands()

这工作得很好,因为输出文件看起来像:

file3.txt
1
2
3
4
5
6

我的问题是为什么 file1.txt 的最后一行(数字 7(没有合并?

省略最后一行,因为zip在较短的可迭代对象的末尾停止。

你想要的可能是

from itertools import zip_longest
def merge_lines():
with open("file1.txt") as f1,
open("file2.txt") as f2,
open("file3.txt", "w") as tfile:
for l1, l2 in zip_longest(f1, f2, fillvalue="Empty line"):
# Or you can place a sentinel value for `fillvalue` 
# and check it and don't write to file when you see it.                
tfile.write(l1.strip() + "n")
tfile.write(l2.strip() + "n")

或者如果您不想写出以归档空行

for l1, l2 in zip_longest(f1, f2, fillvalue=None):
if l1:                           
tfile.write(l1)
if l2:
tfile.write(l2)

并且由于fillvalue的默认值是None,我们可以将其进一步简化为

for l1, l2 in zip_longest(f1, f2):
if l1:                           
tfile.write(l1)
if l2:
tfile.write(l2)

编辑

阅读@DYZ的评论和回答后,进行了以下更改:

  1. 修复了多行"打开"语法错误。不幸的是,我们不能 使用括号对多行"with"语句进行分组。
  2. 添加了第二个选项来检查哨兵值(我已经这样做了( 在我的原始答案中提到(。

使用函数zip_longest,您的代码可以用非常紧凑的方式编写:

from itertools import zip_longest
with open("file1.txt") as f1,
open("file2.txt") as f2,
open("file3.txt", "w") as tfile:
for l1, l2 in zip_longest(f1, f2, fillvalue=''):
if l1 != '': tfile.write(l1)
if l2 != '': tfile.write(l2)

不需要显式读取或类型转换。

正如其他人提到的,这是因为您使用普通的zip((,最长列表(文件(的最后一行被省略了.zip只会形成最多较短列表长度的元组

相反,您可以使用以下扩展 zip 中的任何一个,它将填充到最长的列表

itertools.zip_longest -- in python 3.x +
itertools.izip_longest  --in python 2.6+

表达式zip(f1_lists, f2_lists)返回的元组列表,其长度与提供的可迭代对象中较短的元组列表(在您的案例列表中(一样长。 因此,每个 zip 文档都需要此行为。

如果要包含最后一行,请尝试使用 itertools.ziplongest

from ast import literal_eval
from itertools import ziplongest
def merge_lines():
with open("file1.txt") as f1, open("file2.txt") as f2:
with open("file3.txt", "r+") as tfile:
f1_lists = (literal_eval(line) for line in f1)
f2_lists = (literal_eval(line) for line in f2)
for l1, l2 in zip_longest(f1_lists, f2_lists, fillvalue='x'):
tfile.write(str(l1))
tfile.write("n")
tfile.write(str(l2))
tfile.write("n")
combine_hands()

最新更新