首页 > 解决方案 > 从一个列表的列表中平均结果,其中每个第 n 个列表都是一个重复

问题描述

所以我编写了一个模型,通过嵌套循环计算各种参数的结果。每个计算都返回一个len(columns) = 10元素列表,该列表被添加到列表列表 ( res) 中。

假设我计算了一些参数len(alpha) = 2, len(gamma) = 2,的结果rep = 3,其中 rep 是我运行的重复次数。这会以列表列表的形式产生结果,如下所示:

res = [ [elem_1, ..., elem_10], ..., [elem_1, ..., elem_10] ]

我知道len(res) = len(alpha) * len(gamma) * repetitions = 12并且每个内部列表都有len(columns) = 10元素。我也知道每 3 个列表res都将是一个重复(我从设置嵌套循环以迭代所有参数组合的方式中知道,实际上我正在使用 itertools)。

我现在想平均列表的结果列表。我需要做的是获取每个(len(res) // repetitions) = 4列表,将它们按元素相加,然后除以重复次数(3)。对我来说,听起来容易做起来难。

这是我这样做的丑陋尝试:

# create a list of lists of lists, where the inner list of lists are lists of the runs with the identical parameters alpha and gamma
res = [res[i::(len(res)//rep)] for i in range(len(res)//rep)]

avg_res = []
for i in res:
    result = []
    for j in (zip(*i)):
        result.append(sum(j))
    avg_res.append([i/repetitions for i in result])

print(len(result_list), avg_res)

这实际上产生了我想要的,但它肯定不是 pythonic 的方式。丑得要命,5分钟后我几乎无法理解我自己的代码......

最pythonic的方法是什么?提前致谢!

标签: python

解决方案


在某些情况下,pythonic 代码是一种风格问题,它的一个习惯用法是使用列表推导而不是循环,因此编写result = [sum(j) for j in (zip(*i))]比迭代更简单zip(*i)

另一方面,嵌套列表理解看起来更复杂,所以要这样做

avg_res = [[i/repetitions for i in [sum(j) for j in (zip(*j))]] for j in res]

你可以写:

res = [res[i::(len(res)//rep)] for i in range(len(res)//rep)]

avg_res = []
for i in res:
    result = [sum(j) for j in (zip(*i))]
    avg_res.append([i/repetitions for i in result])

print(len(result_list), avg_res)

编程中的另一个习惯用法(特别是在 python 中)是用函数和变量名命名操作,以使代码更具可读性

def sum_columns(list_of_rows):
  return [sum(col) for col in (zip(*list_of_rows))]
def align_alpha_and_gamma(res):
  return [res[i::(len(res)//rep)] for i in range(len(res)//rep)]

aligned_lists = align_alpha_and_gamma(res)

avg_res = []
for aligned_list in aligned_lists:
    sums_of_column= sum_columns(aligned_list)
    avg_res.append([sum_of_column/repetitions for sum_of_column in sums_of_column])

print(len(result_list), avg_res)

当然,您可以根据要在代码中执行的操作来选择更好的名称。


推荐阅读