使用itertools.groupby的输出错误

时间:2019-04-24 12:13:40

标签: python group-by itertools

我遇到了这个作业问题,参加了有关Udemy的课程后,我仍然不知道如何获得正确的输出,如解决方案。

此外:如何提高效率。在不使用显式循环的情况下如何做到这一点,而是使用列表/字典理解。

这就是我的工作

def group_permutation_values(permutations_list): 

    dic = {}
    f = lambda x: x[1]
    for key, group in itertools.groupby(sorted(permutations_list, key=f), f):
        dic[key] = list(group)

    return dic

    pass

results = [
    ((1, 2, 3), -4),
    ((1, 3, 2), -4),
    ((2, 1, 3), -2),
    ((2, 3, 1), -2),
    ((3, 1, 2), 0), 
    ((3, 2, 1), 0)
]
print(group_permutation_values(results))

这就是我得到的:

{
    -4: [((1, 2, 3), -4), ((1, 3, 2), -4)],
    -2: [((2, 1, 3), -2), ((2, 3, 1), -2)],
     0: [((3, 1, 2), 0), ((3, 2, 1), 0)]
}

预期输出:

{
    -4: [(1, 2, 3), (1, 3, 2)],
    -2: [(2, 1, 3), (2, 3, 1)],
     0: [(3, 1, 2), (3, 2, 1)]
}

1 个答案:

答案 0 :(得分:1)

groupby的键函数仅确定如何对值进行分组;该功能不用于更改组元素本身。仅仅因为您按element[1]进行分组,并不意味着这些组将只包含element[0],就得到了整个元组。

您需要做的就是在创建列表值时首先从组的每个元素中提取嵌套的元组:

dic[key] = [t[0] for t in group]

因此,在list(group)返回[((1, 2, 3), -4), ((1, 3, 2), -4)]的情况下,上述列表推导会生成[(1, 2, 3), (1, 3, 2)]

您可以用字典理解替换for的外部groupby循环来构建字典,

def group_permutation_values(permutations_list): 
    f = lambda x: x[1]
    sorted_list = sorted(permutations_list, key=f)
    return {k: [t[0] for t in g] for k, g in itertools.groupby(sorted_list, f)}

但是,在这里使用groupby()是错误的工具。 groupby()要求您首先对输入进行排序,这会降低性能。排序是一个O(N log N)操作,但是只需在O(N)线性时间内将元组存储到字典中,只需循环输入列表并为每个条目附加一个列表即可。

def group_permutation_values(permutations_list):
    grouped = {}
    for a, b in permutations_list:
        grouped.setdefault(b, []).append(a)
    return grouped

这不能转化为字典理解,但是效率更高。理解力不是万能的,它只是通过处理可迭代对象中的每个元素来创建容器(列表,字典,集合)的语法。是的,它们比等效的for带容器添加循环的效率要高一些,但是它们仍然受常规算法时间复杂度的影响。