【问题标题】:Summation of specific items in a nested list嵌套列表中特定项目的总和
【发布时间】:2014-09-30 19:22:04
【问题描述】:

我有一个数据文件,例如:

1  123  something else
2  234  something else
3  500  something else
.
. 
.
1  891  something else
2  234  something else
3  567  something else 
.
.
.

我试图最终得到一个文件:

1 1014
2  468
3 1067

也就是说,如果第 1 列中的数字相同,则添加第 2 列(或其他列)中的数字。我相信将列读入嵌套列表并从那里开始是可行的,但我一直在努力解决这个问题。我尝试的另一种方法是使用我感兴趣的条目创建一个新文件:

for next in f.readlines():
    output.write(next[0:1] + "," + next[3:6]+ "\n")
    if not next:
        break

with open(output,"r") as file:
    data_list=[[int(x) for x in line.split(",")] for line in file]

print data_list

返回

[[1, 123], [2, 234], [3, 500], [1, 891], [2, 234], [3, 567]]

我想我可以遍历该列表并比较 data_list[x][0] 并添加匹配的值,但这似乎不是一个优雅的解决方案。 谁能提出一种更优雅的方式来做到这一点? 特别是,我一直在努力对最终得到的嵌套列表中的特定项目求和。

【问题讨论】:

  • 使用列表中的dictionary{1: [123, 891, ...], ...}
  • 您的代码示例没有意义。什么是输出?为什么不直接使用文件对象 f 工作?并且...我不会那么明确地采用 next[3:6],但也许用 .split('\t') 分割行并采用 [1] 元素
  • 感谢 cmets 并对造成的混乱表示歉意。我省略了一些代码以使其更具可读性,我猜它会产生相反的效果。无论如何,明确采用 next[3:6] 的原因是由于数据文件的设置方式,这是我无法控制的。

标签: python list nested


【解决方案1】:

使用字典来跟踪总和;使用 collections.defaultdict() 可以更容易地从 0 开始键,如果它们以前没有见过:

from collections import defaultdict

sums = defaultdict(int)

with open(filename) as f:
    for line in f:
        col1, col2, rest = line.split(None, 2)
        sums[col1] += int(col2)

这会读取您的初始文件,将空白行拆分 2 次以取出前两列,然后根据第一列对第二列求和:

>>> from collections import defaultdict
>>> sample = '''\
... 1  123  something else
... 2  234  something else
... 3  500  something else
... 1  891  something else
... 2  234  something else
... 3  567  something else 
... '''.splitlines()
>>> sums = defaultdict(int)
>>> for line in sample:
...     col1, col2, rest = line.split(None, 2)
...     sums[col1] += int(col2)
... 
>>> sums
defaultdict(<type 'int'>, {'1': 1014, '3': 1067, '2': 468})

【讨论】:

  • 感谢您的建议!我在最初的帖子中没有包含此内容,但实际上我使用的数据文件有时包含大量数字,因此列之间不存在空格。相反,列被预定义为例如 column1:1-4,column2:5-7。有没有办法将 col1 定义为字符 [0:4],将 col2 定义为字符 [5:7] 等?希望这是有道理的。如果这不能很容易地合并,我将按照我的原始帖子制作一个新文件,然后使用您提供的代码。
  • @user2913053:然后像这样分割你的数字;而不是line.split(),只需使用col1 = line[:4].strip()(切片后删除多余的空格)和col2 = int(line[5:7])sums[col1] += col2
  • 我认为您也应该将密钥转换为 int,否则我也非常喜欢这个解决方案;)
  • 我假设第一列是一个不透明的值;它可能是一个 int 或其他东西。如果我们将其保留为字符串或将其转换为 int,则此处分组无关紧要。
猜你喜欢
  • 2021-03-20
  • 2020-05-04
  • 1970-01-01
  • 2021-05-18
  • 2018-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多