【问题标题】:For-loop not inserting a line break when using zip_longest in Python 3在 Python 3 中使用 zip_longest 时,for 循环不插入换行符
【发布时间】:2021-11-23 23:18:24
【问题描述】:

我正在编写一个简单的文本比较工具。它需要两个文本文件——一个模板和一个目标——并使用两个 for 循环比较每行中的每个字符。任何差异都使用 Unicode 完整块符号 (\u2588) 突出显示。在目标行比模板长的情况下,我使用 itertools.zip_longest 用填充值填充不存在的字符。

from itertools import zip_longest

def compare(filename1, filename2):
    
    file1 = open(filename1, "r")
    file2 = open(filename2, "r")
    
    for line1, line2 in zip_longest(file1, file2):
    
        for char1, char2 in zip_longest(line1, line2, fillvalue=None):
            
            if char1 == char2:
                print(char2, end='')
            
            elif char1 == None:
                print('\u2588', end='')

compare('template.txt', 'target.txt')
Template file:        Target file:

First line            First lineXX
Second line           Second line
Third line            Third line

但是,这似乎与 Python 的自动换行符位置相混淆。当一行以这样的填充值结束时,不会生成换行符,给出这样的结果:

First line██Second line
Third line

代替:

First line██
Second line
Third line

在重写脚本以使用 .append 和 .join(未显示以保持简短)后问题仍然存在,尽管它允许我突出显示问题:

Result when both files are identical:

['F', 'i', 'r', 's', 't', ' ', 'l', 'i', 'n', 'e', '\n']
First line
['S', 'e', 'c', 'o', 'n', 'd', ' ', 'l', 'i', 'n', 'e', '\n']
Second line
['T', 'h', 'i', 'r', 'd', ' ', 'l', 'i', 'n', 'e']
Third line

Result when first line of target file has two more characters:

['F', 'i', 'r', 's', 't', ' ', 'l', 'i', 'n', 'e', '█', '█']
First line██['S', 'e', 'c', 'o', 'n', 'd', ' ', 'l', 'i', 'n', 'e', '\n']
Second line
['T', 'h', 'i', 'r', 'd', ' ', 'l', 'i', 'n', 'e']
Third line

如您所见,如果行的长度相同,Python 会自动添加换行符 \n,但是一旦涉及 zip_longest,列表中的最后一个字符就是块,而不是换行符。为什么会这样?

【问题讨论】:

  • 这不是因为 Python 自动添加换行符(它没有),而是因为换行符在数据中。文本文件在每行末尾都有一个换行符。
  • @BoarGules 这比我最初的假设更有意义,感谢您的洞察力。

标签: python loops for-loop itertools line-breaks


【解决方案1】:

在比较字符之前剥离你的行并在每行之间打印新行:

from itertools import zip_longest

def compare(filename1, filename2):
    
    file1 = open(filename1, "r")
    file2 = open(filename2, "r")
    
    for line1, line2 in zip_longest(file1, file2):
        line1, line2 = line1.strip(), line2.strip()  # <- HERE

        for char1, char2 in zip_longest(line1, line2, fillvalue=None):
            
            if char1 == char2:
                print(char2, end='')

            elif char1 == None:
                print('\u2588', end='')
        print()  # <- HERE

compare('template.txt', 'target.txt')

【讨论】:

  • 工作精美,回复迅速,感谢您的帮助!没有足够的声誉来投票,所以请从我这里获得荣誉投票。
  • 重要的是你的问题已经解决了,仅此而已。
猜你喜欢
  • 1970-01-01
  • 2017-01-02
  • 1970-01-01
  • 1970-01-01
  • 2022-07-30
  • 1970-01-01
  • 2015-06-21
  • 2013-08-05
  • 1970-01-01
相关资源
最近更新 更多