【问题标题】:How to force every line to have the same # of tabs as the maximum length line如何强制每行具有与最大长度行相同的标签数
【发布时间】:2014-07-25 08:09:16
【问题描述】:

我有一个制表符分隔的 txt,我想让每一行的制表符数量与制表符数量最多的行相同。

例如,

A\tB\tC\tD
E\t
F\tG\t

输入文件:https://drive.google.com/file/d/0B1sEqo7wNB1-bmpKaWdrSmUtcUE/edit?usp=sharing 会变成

A\tB\tC\tD
E\t\t\t
F\tG\t\t

我正在尝试这个。

import sys
from itertools import izip_longest
import codecs

inputf  = sys.argv[1]
outputf  = sys.argv[2]

with open(inputf) as f:
    data = izip_longest(*(x.split('\t') for x in f), fillvalue='\t')
for line in zip(*data):
    print line,

ofile = codecs.open(outputf, "w")

但是输出什么都没有,尽管它在命令窗口中打印了东西。

我希望这个程序不会在命令窗口中打印这些(似乎需要很多时间)

我希望输出文件有正确的输出。

【问题讨论】:

    标签: python csv


    【解决方案1】:

    尝试使用 csv 模块,像这样

    #!/usr/bin/env python
    import sys
    import csv
    from itertools import izip_longest
    
    def read_rows(inputfile):
        with open(inputfile, 'rb') as h:
            reader = csv.reader(h, dialect='excel-tab')
            return list(reader)
    
    def write_rows(outputfile, rows):
        with open(outputfile, 'wb') as h:
            writer = csv.writer(h, dialect='excel-tab')
            for row in rows:
                writer.writerow(row)
    
    def show_file(outputfile):
        with open(outputfile, 'r') as h:
            print h.read().splitlines()
    
    def main(inputfile, outputfile):
        rows = read_rows(inputfile)
        rows = zip(*(izip_longest(*rows, fillvalue='')))
        write_rows(outputfile, rows)
        show_file(outputfile)
    
    if __name__ == '__main__':
        inputfile = sys.argv[1]
        outputfile = sys.argv[2]
        main(inputfile, outputfile)
    

    使用您的输入文件:

    ./normalize.py ~/Downloads/input.txt ~/Downloads/output.txt 
    ['A\tB\tC\tD', 'E\t\t\t', 'F\tG\t\t']
    

    【讨论】:

    • write_rows() 函数中,您可以只使用一个writer.writerows(rows) 调用而不是for 循环。此外,可能不需要 show_file() 函数,因为 OP 抱怨将输出打印到命令窗口花费了太多时间。
    【解决方案2】:

    您在命令窗口中看到了输出,因为您正在打印data 中的内容(它使用izip_longest() 返回的迭代器)。文件中没有任何内容,因为从未向其中写入任何数据,您只是为了写入而打开它。

    我相信以下内容会(仅)做你想要的:

    import sys
    from itertools import izip_longest
    import codecs
    
    inputf = sys.argv[1]
    outputf = sys.argv[2]
    
    with open(inputf) as f:
        data = izip_longest(*(x.strip().split('\t') for x in f), fillvalue='')
    
    with codecs.open(outputf, "w") as ofile:
        ofile.write('\n'.join('\t'.join(items) for items in zip(*data)) + '\n')
    

    【讨论】:

      【解决方案3】:
      But output has nothing although it prints things in command window.
      

      这是因为您没有将数据写入文件。

      如下改变你的程序

      with open(inputf) as fin, open(outputf, "w") as fout:
          data = izip_longest(*(x.split('\t') for x in fin), fillvalue='\t')
          fout.write('\n'.join(map(''.join, zip(*data))))
      

      请注意,您的程序可能无法提供所需的输出,因为换行符是您要压缩的元素列表中字符的一部分。您需要从读取的行中去掉换行符

          data = izip_longest(*(x.strip().split('\t') for x in f), fillvalue='\t')
      

      【讨论】:

      • 也许第二个 inputf 应该是 outputf ?
      • 我测试了您的原始代码,然后显示“名称 f 未定义”。所以我用“x in fin”替换了“x in f”,但这并没有提供任何输出,然后将第二个inputf更改为outputf,同样的问题发生了。
      猜你喜欢
      • 2016-01-17
      • 1970-01-01
      • 2023-03-09
      • 2018-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多