使用map函数迭代Python

时间:2018-01-03 15:20:28

标签: python list sorting dictionary list-comprehension

我一直在尝试处理存储在词典列表中的数据,并将其存储在另一个元组列表中。例如,说我有以下数据:

triangles= [{"name": "triangle1", "base":3, "height":4}, 
            {"name": "triangle2", "base":5, "height":12}, 
            {"name": "triangle3", "base":8, "height":15}
           ]

我想通过以下函数运行所有数据,我无法改变:

def hypotenuse(base, height):
    hyp_sq=base**2+height**2

    return hyp_sq**(1.0/2.0)

理想情况下,在计算完所有数据后,我想根据它们的斜边长度对三角形进行排序,我想以下列格式返回元组列表:

hypotenuse_results=[("triangle1", 5), ("triangle2", 13), ("triangle3", 17)]

我知道我必须结合sorted()使用map()函数,但我不知道如何仅传递对应于" base"的值。和"身高"键。

如果有人能指出我正确的方向,我们将不胜感激。

由于

3 个答案:

答案 0 :(得分:6)

1993年左右,Python得到了lambda,reduce(),filter()和map(),这是一个错过了他们并提交工作补丁的Lisp黑客的礼貌。在2000年引入列表推导之后,这些Lisp风格的构造在Python中被认为是有点陌生​​。所以不,你不需要map,你可以使用列表推导或生成器表达式。

您可以让hypotenuse函数采用额外的参数并忽略它们:

def hypotenuse(base, height, **kwargs):
    hyp_sq=base**2+height**2
    return hyp_sq**(1.0/2.0)

然后你可以使用列表理解:

hypotenuse_results = [(t['name'], hypotenuse(**t)) for t in triangles]
hypotenuse_results.sort(key=lambda pair: pair[1])

即使对于大len(triangles),这也应该足够好。生成器表达式版本为:

unsorted_results = ((t['name'], hypotenuse(**t)) for t in triangles)
hypotenuse_results = sorted(unsorted_results, key=lambda pair: pair[1])

分析两种解决方案并在此处发布将是一项很好的练习。

  

感谢。有没有办法解决这个问题而不修改斜边函数? - canecse

当然!只需用两个参数调用它:

hypotenuse_results = [(t['name'], hypotenuse(t['base'], t['height'])) for t in triangles]
hypotenuse_results.sort(key=lambda pair: pair[1])

请注意,接受的解决方案是分配一个实际的列表并将其抛弃,这样如果您担心内存占用,则可能需要使用生成器表达式而不是列表解析(如果len(triangles)很大但特别有用但是总是一个好习惯):

hypotenuse_results = sorted(
    ((t['name'], hypotenuse(t['base'], t['height'])) for t in triangles), 
    key=lambda x: x[1]
)

答案 1 :(得分:3)

你需要修改你的斜边函数,对于这样的一些:

def hypotenuse(triangle):
    hyp_sq=triangle["base"]**2 + triangle["height"]**2
    return (triangle["name"], hyp_sq**(1.0/2.0))

map将返回一个元组生成器,当每个元组是(name,hyp)时,只需使用元组的第二个元素进行排序:

sorted(map(hypotenuse, triangles), key=lambda x: x[1])

更新:

因为你无法改变斜边功能,你只需使用列表理解:

sorted([(t['name'], hypotenuse(t['base'], t['height'])) for t in triangles], key=lambda x: x[1])

答案 2 :(得分:3)

由于您的hypotenuse函数在这里工作正常,您可以构建一个理解来创建元组列表:

from operator import itemgetter

result = sorted(((x['name'], hypotenuse(x['base'], x['height'])) for x in triangles), key = itemgetter(1))

print(result)

给出了:

[('triangle1', 5), ('triangle2', 13), ('triangle3', 17)]

或者如果你真的想使用map(),你可以试试这个:

result = sorted(map(lambda x: (x['name'], hypotenuse(x['base'], x['height'])), triangles), key = itemgetter(1))

注意:您可以使用lambda x: x[1]代替operator.itemgetter(1)。这只是一个偏好问题。如果您有兴趣,可以阅读this以了解两者之间的表现,以及各自的利弊。

<强>更新

@Paulo Scardine在评论中指出,如果triangle将来变得更大,在sorted()中使用生成器表达式会更有效率。这是因为列表推导会在现场创建一个列表,但sorted()在此过程中会删除此列表,因此在不需要时将列表传递到列表中是浪费。对于第二个示例,这不是问题,因为map()已经返回了生成器。我更新了上述代码以说明这些建议。