问题: 在某集合中找出最大或最小的N个元素

heapq模块: nlargest( ), nsmallest( )

import heapq


nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
print(heapq.nlargest(3, nums))
print(heapq.nsmallest(3, nums))

portinfo = [
{'name': 'IBM', 'shares': 100, 'price': 91.1},
{'name': 'AAPL', 'shares': 50, 'price': 543.22},
{'name': 'FB', 'shares': 200, 'price': 21.09},
{'name': 'HPQ', 'shares': 35, 'price': 31.75},
{'name': 'YHOO', 'shares': 45, 'price': 16.35},
{'name': 'ACME', 'shares': 75, 'price': 115.65},
]

cheap = heapq.nsmallest(3, portinfo, key=lambda s: s['price'])
expensive = heapq.nlargest(3, portinfo, key=lambda s: s['price'])
print(cheap, expensive)

lambda表达式通常是在需要一个函数,但简单起见不想命名它的场合下使用,即匿名函数,

所表示的匿名函数的内容应该是很简单的,如果复杂的话,干脆就重新定义一个函数了,使用lambda就有点过于执拗了。


lambda就是用来定义一个匿名函数的,如果还要给他绑定一个名字的话,就会显得有点画蛇添足,通常是直接使用lambda函数。如下所示:


add = lambda x, y : x+y
add(1,2)  # 结果为3
 

如何使用lambda表达式呢?

1、应用在函数式编程中


Python提供了很多函数式编程的特性,如:map、reduce、filter、sorted等这些函数都支持函数作为参数,lambda函数就可以应用在函数式编程中。如下:


# 需求:将列表中的元素按照绝对值大小进行升序排列
list1 = [3,5,-4,-1,0,-2,-6]
sorted(list1, key=lambda x: abs(x))

常规方法:


list1 = [3,5,-4,-1,0,-2,-6]
def get_abs(x):
    return abs(x)
sorted(list1,key=get_abs)

2、应用在闭包中

def get_y(a,b):
     return lambda x:ax+b
y1 = get_y(1,1)
y1(1) # 结果为2

当然,也可以用常规函数实现闭包,如下:

def get_y(a,b):
    def func(x):
        return ax+b
    return func
y1 = get_y(1,1)
y1(1) # 结果为2

Explicit is better than implicit(明了胜于晦涩),就是说那种方式更清晰就用哪一种方式,不要盲目的都使用lambda表达式。

讨论:

1)如果同集合中的元素总数相比N很小,那么堆排序可以提供更好的性能:

堆最重要的特性就是heap[0]总是最小的元素,heapq.pop()会将第一个元素弹出,并用第二小的元素取代 操作复杂度log(N)

2)要找的元素数量相对较小时,函数nsmallest()和nlargest()才是最适用的

3)单纯要找最小或最大的元素,min()和max()会更快

4)N和元素总数差不多,先对集合排序再做切片操作sorted(items)[:N]或sorted(items)[-N:]

注:nlargest和nsmallest的实际实现会根据使用它们的方式而有所不同,可能相应作出一些优化措施,如当N与总数接近就会采用排序法

posted on 2018-07-18 14:52  浅塘  阅读(716)  评论(0编辑  收藏  举报