在文本文件内容中的某些项目中执行计算并将结果分组在 python 中

Perform calculation in some items in a text file content and group the results in python

我正在尝试对文本文件内容执行一些计算和分组。我已经对数据进行了分组,但仍然存在问题,而且我不知道如何在最后一个字段(金额列)上执行计算。

from collections import defaultdict
data=defaultdict(int)
with open('datafile.txt') as f:
    for line in f:
        group, score, team = line.split(maxsplit=2)
        data[(group.strip(),team.replace('\n','').strip())]+=int(score)
sorteddata = sorted([[k[0],v,k[1]] for k,v in data.items()], key=lambda x:x[1], reverse=True)

for subl in sorteddata:
    print(" ".join(map(str, subl)))

datafile.txt(项目、交易、金额)

alpha 1 54,00.01
bravo 3 500,000.00
charlie 1 27,722.29 (0.45)
charlie 10 252,336,733.383 (2.06)
delta 2 11 ()
echo 5 143,299.00 (1)
echo 8 145,300 (5.01)
falcon 3 0.1234
falcon 5 9.19
lima 6 45.00181 (.9)
romeo 12 980

想要的输出:#-- 排序、分组和计算

echo    13  288,599.00 (6.01)      #-- grouped and calculated
romeo   12  980
charlie 11  252,364,455.673 (2.51) #-- grouped and calculated
falcon  8   9.3134                    #-- grouped and calculated
lima    6   45.00181 (.9)
bravo   3   500,000.00
delta   2   11 ()
alpha   1   54,00.01

当前输出:#-- 部分正确

romeo 12 980
charlie 10 252,336,733.383 (2.06)
echo 8 145,300 (5.01)
lima 6 45.00181 (.9)
echo 5 143,299.00 (1)
falcon 5 9.19
bravo 3 500,000.00
falcon 3 0.1234
delta 2 11 ()
alpha 1 54,00.01
charlie 1 27,722.29 (0.45)

这里有很多问题,但首先,您希望为每个团队添加三个单独的值,其中一些在您的代码中显然是可选的。仅仅拆分、分组、添加并希望获得最佳效果并不能解决问题。

编写代码时,请始终通盘考虑整个问题,并在编写代码时尝试在脑海中想象/想象过程。每行代码都应该对应于你想要发生的具体事情。编码中没有 'taking a stab at it'。

您似乎试图通过设置 maxsplit 来覆盖可选的最后一列,但您仍然需要处理最后一个字段,因为您希望它出现在输出中。

Python 也不可能自动处理 (.9) 之类的东西并将其理解为数值 - 你必须告诉它。

我假设像 54,00.01 这样的输入是一个拼写错误并且应该读作 54,000.01 因为你使用的是普通的英文数字?

这是您的程序的一个版本,与您编写的版本有些接近:

data = {}

with open('datafile.txt') as f:
    for line in f:
        parts = line.split()
        team, a, b, c = parts if len(parts) == 4 else parts + ['([=10=])']
        data[team] = tuple(map(sum, zip((int(a), float(b.replace(',', '')), float(c[2:-1].replace(',', ''))), data.get(team, (0, 0, 0)))))

data = {t: (a, b, c) for a, b, c, t in reversed(sorted((a, b, c, t) for t, (a, b, c) in data.items()))}

for team, (a, b, c) in data.items():
    print(f'{team:8} {a:4} {b:,} (${c:,})')

还需要进行一些更改,您可以看到 c 的最终值为 0 的值仍会打印出来,但修复问题留给了 reader。结果:

echo       13 288,599.0 (6.01)
romeo      12 980.0 ([=11=].0)
charlie    11 252,364,455.67299998 (2.51)
falcon      8 9.3134 ([=11=].0)
lima        6 45.00181 (.9)
bravo       3 500,000.0 ([=11=].0)
delta       2 11.0 (.0)
alpha       1 54,000.01 ([=11=].0)

关于解决方案的一些注意事项:添加是通过以下行完成的:

data[team] = tuple(map(sum, zip((int(a), float(b.replace(',', '')), float(c[2:-1].replace(',', ''))), data.get(team, (0, 0, 0)))))

通过获取现有的元组,或者 (0, 0, 0) 如果它不存在(而不是使用 defaultdict)。它是一个包含当前行值的元组的 zips,这些值根据需要从字符串形式转换为数字形式。然后 sum 函数被映射到两个元组的值对上(将它们相加),最后,结果再次变成元组。

您似乎按 'a' 排序,但我假设如果两个团队在那里具有相同的值,您可能希望按这两个数字排序,所有内容均按团队名称排序:

data = {t: (a, b, c) for a, b, c, t in reversed(sorted((a, b, c, t) for t, (a, b, c) in data.items()))}

这是通过获取生成的字典,将其转换为元组,对它们进行排序,反转结果然后再次将其转换为字典来实现的(当然您也可以只获取元组列表并打印它们)

漂亮版式的印刷很干净:

    print(f'{team:8} {a:4} {b:,} (${c:,})')

这是一个所谓的 f 字符串,它负责用逗号格式化浮点数,并为示例输出中的列设置特定大小。