【问题标题】:sum up values according to string condition of a list generated by a for loop根据 for 循环生成的列表的字符串条件对值求和
【发布时间】:2017-04-19 05:23:46
【问题描述】:

我的代码搜索特定文件并调用单独的 .py 文件来输出一些数据。我手动为每个文件的文件大小附加了一行。我只是想将找到的文件的所有文件大小的总和附加到迭代的末尾。我想这将涉及使用布尔索引,但是我找不到任何好的参考。我想找到所有标记为“文件大小”的列,然后将它们的所有值相加。


一个样本迭代(我随机将许多“文件大小”彼此靠近,但在实际数据中,它会被大约 15 行分开)

xd = """Version 3.1.5.0
GetFileName C:\\users\\trinh\\downloads\\higgi022_20150612_007_bsadig_100fm_aft_newIonTrap3.raw
GetCreatorID    thermo
GetVersionNumber    64
file size   1010058
file size   200038
file size   48576986
file size   387905
misc    tester
more    python"""

在 for 循环结束时,我想对所有文件大小求和(这是非常错误的,但这是我的最佳尝试):

zd = xd.split()
for aline in zd:
    if 'file size' in aline:
        sum = 0
        for eachitem in aline[1:]:
            sum += eaechitem
            print(sum)

【问题讨论】:

  • 试着想想你的具体问题是什么,并尽量减少帖子,使其只包含相关代码和信息
  • sum(k) ??什么都不做。
  • 嗨 Ni,我删掉了与问题无关的代码并添加了一些 cmets。也许更清楚我要做什么?

标签: python python-3.x csv sum export-to-csv


【解决方案1】:

对于您提供的示例数据,要获取以file size 开头的所有行的总数,您可以执行以下操作:

xd = """Version 3.1.5.0
GetFileName C:\\users\\trinh\\downloads\\higgi022_20150612_007_bsadig_100fm_aft_newIonTrap3.raw
GetCreatorID    thermo
GetVersionNumber    64
file size   1010058
file size   200038
file size   48576986
file size   387905
misc    tester
more    python"""

total = 0

for line in xd.splitlines():
    if line.startswith('file size'):
        total += int(line.split()[2])

print(total)

这将显示:

50174987

这首先将xd 分成几行,并为每一行确定它是否以单词file size 开头。如果是,则使用 split() 将行分成 3 部分。第三部分包含大小为字符串,因此需要使用int()将其转换为整数。


要将其扩展到文件上,您首先需要读取文件并汇总必要的行,然后以追加模式打开它以写入总数:

with open('data.txt') as f_input:
    total = 0

    for line in f_input:
        if line.startswith('file size'):
            total += int(line.split()[2])

with open('data.txt', 'a') as f_output:
    f_output.write("\nTotal file size: {}\n".format(total))

根据您当前的脚本,您可以将其合并如下:

import os
import csv
from subprocess import run, PIPE

pathfile = 'C:\\users\\trinh\\downloads'
msfilepath = 'C:\\users\\trinh\\downloads\\msfilereader.py'

file_size_total = 0

with open("output.csv", "w", newline='') as csvout:
    writer = csv.writer(csvout, delimiter=',')

    for root, dirs, files in os.walk(pathfile):
        for f in files:
            if f.endswith(".raw"):
                fp = os.path.join(root, f) #join the directory root and the file name
                p = run(['python', msfilepath, fp], stdout=PIPE) #run the MSfilereader.py path and each iterated raw file found
                p = p.stdout.decode('utf-8')

                for aline in p.split('\r\n'):
                   header = aline.split(' ', 1)
                   writer.writerows([header])

                   if 'END SECTION' in aline and aline.endswith('###'):
                        file_size = os.stat(fp).st_size
                        file_size_total += file_size
                        lst_filsz = ['file size', str(file_size)]
                        writer.writerow(lst_filsz)

    writer.writerow(["Total file size:", file_size_total])

这将为您提供总共所有 file size 条目。如果需要,也可以为每个部分添加小计。

注意,在使用with open(....时,文件不需要同时添加close(),只要离开with语句的作用域,文件就会自动关闭。

【讨论】:

  • 嗨,马丁,感谢您的回答,感谢您的帮助。我确信您的代码可以工作,但我无法将它实现到我现有的代码中。我使用 for 循环 + writerows 为从单独的 .py 文件中找到的每个文件生成数据,并在此循环结束时使用查找每次迭代的最后一行的 if 语句手动添加文件大小。我想这不是很好的技术,但我让它做我想做的事。但是,我不知道如何遍历“文件大小”行,因为(我认为)它不存在先验。它没有什么可以迭代来总结文件大小
  • 如果您使用的是csv,那么只需在关闭文件之前添加类似:csv_output.writerow(['total size', total])(在循环之外)
  • 也许您可以将您的脚本复制到诸如0bin.net 之类的站点上,然后在此处发布指向它的链接。
  • 嗨马丁,这里是 0bin.net 托管的链接:0bin.net/paste/hnnJ2ZM7XpKYAX+v#
  • 不要以为你发布了正确的链接,那里只有一个 JSON 对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-12
  • 2018-02-04
  • 1970-01-01
相关资源
最近更新 更多