需求

K长的序列,求TopN

K长的序列,求BtmN

排序问题

解决

  • heap.nlargest()、heap.nsmallest( )
  • sorted( )+切片
  • max( )、min( )

总结和比较

1)在Top N问题中,如果 N=1,则直接用max(iterable)/min(iterable) 即可(效率最高)。

2)如果N很大,接近集合元素,则为了提高效率,采用 sort+切片 的效率会更高,如:

  1. 求最大的N个元素:sorted(iterable, key=key, reverse=True)[:N]
  2. 求最小的N个元素:sorted(iterable, key=key)[:N]

3)当要查找的元素个数相对比较小的时候,使用 nlargest() 和 nsmallest() 是很合适的

详解max( )/min( )函数用法

  • 求简单的序列TopN/BtmN(N=1)问题
  1. lst=[1,2,3,4,5]
  2. print(max(lst))
  3. 5
  • 通过key属性的使用,设置函数条件为判断的标准
  1. a=[-9,-8,1,3,-4,6]
  2. print(max(a,key=lambda x:abs(x)))
  3. -9
  • 找出字典中值最大的那组数据
  1. prices = {
  2. 'A':123,
  3. 'B':450.1,
  4. 'C':12,
  5. 'E':444,
  6. }
  7. //在对字典进行数据操作的时候,默认只会处理key,而不是value
  8. //先使用zip把字典的keys和values翻转过来,再用max取出值最大的那组数据
  9. max_prices=max(zip(prices.values(),prices.keys()))
  10. print(max_prices)
  11. (450.1, 'B')

nlargest( )/nsmallest( )详解

  • nlargest(n,iterable) 求序列iterable中的TopN | nsmallest(n,iterable) 求序列iterable中的BtmN
  1. import heapq
  2. nums=[16,7,3,20,17,8,-1]
  3. print(heapq.nlargest(3,nums))
  4. print(heapq.nsmallest(3,nums))
  5. [20, 17, 16]
  6. [-1, 3, 7]
  • nlargest(n, iterable, key=lambda) | nsmallest(n, iterable, key=lambda) key接受关键字参数,用于更复杂的数据结构中
  1. def print_price(dirt):
  2. for i in dirt:
  3. for x,y in i.items():
  4. if x=='price':
  5. print(x,y)
  6. portfolio = [
  7. {'name': 'IBM', 'shares': 100, 'price': 91.1},
  8. {'name': 'AAPL', 'shares': 50, 'price': 543.22},
  9. {'name': 'FB', 'shares': 200, 'price': 21.09},
  10. {'name': 'HPQ', 'shares': 35, 'price': 31.75},
  11. {'name': 'YHOO', 'shares': 45, 'price': 16.35},
  12. {'name': 'ACME', 'shares': 75, 'price': 115.65}
  13. ]
  14. cheap=heapq.nsmallest(3,portfolio,key=lambda x:x['price'])
  15. expensive=heapq.nlargest(3,portfolio,key=lambda y:y['price'])
  16. print_price(cheap)
  17. print_price(expensive)
  18. price 16.35
  19. price 21.09
  20. price 31.75
  21. price 543.22
  22. price 115.65
  23. price 91.1

sorted( )详解

  • sorted(iterable, key=None, reverse=False)
  • reverse=True 逆序
  1. nums=[16,7,3,20,17,8,-1]
  2. print(sorted(nums))
  3. print(sorted(nums,reverse=True))
  4. [-1, 3, 7, 8, 16, 17, 20]
  5. [20, 17, 16, 8, 7, 3, -1]
  6. str=['b','a','A','s']
  7. print(sorted(str))
  8. print(sorted(str,reverse=True))
  9. ['A', 'a', 'b', 's']
  10. ['s', 'b', 'a', 'A']
  • key接受一个函数,且是个只接受一个元素的函数
  • 多条件的key应该怎么写?
  1. //按长度排序
  2. L = [{1:5,3:4},{1:3,6:3},{1:1,2:4,5:6},{1:9}]
  3. print(sorted(L,key=lambda x: len(x)))
  4. [{1: 9}, {1: 5, 3: 4}, {1: 3, 6: 3}, {1: 1, 2: 4, 5: 6}]
  1. //根据指定的值来排序(例如字典中的某个key)
  2. L = [

  3. ('john', 'A', 15),

  4. ('jane', 'B', 10),

  5. ('dave', 'B', 12),

  6. ]

  7. print(sorted(L,key=lambda x:x[2],reverse=True))

  8. [('john', 'A', 15), ('dave', 'B', 12), ('jane', 'B', 10)]

  9. portfolio = [

  10. {'name': 'IBM', 'shares': 100, 'price': 91.1},

  11. {'name': 'AAPL', 'shares': 50, 'price': 543.22},

  12. {'name': 'FB', 'shares': 200, 'price': 21.09},

  13. {'name': 'HPQ', 'shares': 35, 'price': 31.75},

  14. {'name': 'YHOO', 'shares': 45, 'price': 16.35},

  15. {'name': 'ACME', 'shares': 75, 'price': 115.65}

  16. ]

  17. print(sorted(portfolio,key=lambda x:x['price']))

  18. [{'shares': 45, 'name': 'YHOO', 'price': 16.35}, {'shares': 200, 'name': 'FB', 'price': 21.09}, {'shares': 35, 'name': 'HPQ', 'price': 31.75}, {'shares': 100, 'name': 'IBM', 'price': 91.1}, {'shares': 75, 'name': 'ACME', 'price': 115.65}, {'shares': 50, 'name': 'AAPL', 'price': 543.22}]
  1. //不规则字符串,按“小写-大写-奇数-偶数”顺序排序

  2. s = 'asdf234GDSdsf23'

  3. print("".join(sorted(s, key=lambda x: (x.isdigit(),x.isdigit() and int(x) % 2 == 0,x.isupper(),x))))

  4. addffssDGS33224
  1. //一道面试题:要求:正数在前负数在后 2.整数从小到大 3.负数从大到小

  2. list1=[7, -8, 5, 4, 0, -2, -5]

  3. print(sorted(list1,key=lambda x:(x<0,abs(x))))

  4. [0, 4, 5, 7, -2, -5, -8]

  • 用operator中的函数加快速度和进行多级排序
  1. from operator import itemgetter, attrgetter
  2. 暂不讨论

比较三种方法的效率

  • 只求TopN=1/BtmN=1时,比较max( )和nlargest( )两种效率
  1. In [8]: nums=random.sample(range(1,10000),999)
  2. In [9]: print(max(nums))
  3. 9999
  4. In [10]: %time
  5. CPU times: user 0 ns, sys: 0 ns, total: 0 ns
  6. Wall time: 13.1 µs
  7. In [11]: heapq.nlargest(1,nums)
  8. Out[11]: [9999]
  9. In [12]: %time
  10. CPU times: user 0 ns, sys: 0 ns, total: 0 ns
  11. Wall time: 14.1 µs
  • 当K为10,N为9(即N无限接近K时),比较了sorted( )+切片和nlargest( )两种方法的效率
  1. In [23]: nums=random.sample(range(1,10000),10)
  2. In [24]: sorted(nums,reverse=True)[:9]
  3. Out[24]: [8814, 7551, 7318, 5597, 5257, 4437, 4211, 2776, 2440]
  4. In [25]: %time
  5. CPU times: user 0 ns, sys: 0 ns, total: 0 ns
  6. Wall time: 11.4 µs
  7. In [26]: heapq.nlargest(9,nums)
  8. Out[26]: [8814, 7551, 7318, 5597, 5257, 4437, 4211, 2776, 2440]
  9. In [27]: %time
  10. CPU times: user 0 ns, sys: 0 ns, total: 0 ns
  11. Wall time: 154 µs
  • 当N较小时,比较了nlargest( )和sorted( )+切片两种方法
  1. In [18]: nums=[16,7,3,20,17,8,-1]
  2. In [19]: heapq.nlargest(3,nums)
  3. Out[19]: [20, 17, 16]
  4. In [20]: %time
  5. CPU times: user 0 ns, sys: 0 ns, total: 0 ns
  6. Wall time: 4.05 µs
  7. In [21]: sorted(nums,reverse=True)[:3]
  8. Out[21]: [20, 17, 16]
  9. In [22]: %time
  10. CPU times: user 0 ns, sys: 0 ns, total: 0 ns
  11. Wall time: 5.48 µs

以上代码用到的import和show_tree( )

  1. import math
  2. import io
  3. from io import StringIO
  4. import heapq
  5. import random
  6. import time
  7. from functools import wraps
  8. def show_tree(tree, total_width=36, fill=' '):
  9. output =io.StringIO() #创建stringio对象
  10. last_row = -1
  11. for i, n in enumerate(tree): #
  12. if i:
  13. row = int(math.floor(math.log(i+1, 2)))
  14. else:
  15. row = 0
  16. if row != last_row:
  17. output.write('\n')
  18. columns = 2**row
  19. col_width = int(math.floor((total_width * 1.0) / columns))
  20. output.write(str(n).center(col_width, fill))
  21. last_row = row
  22. print(output.getvalue())
  23. print('-' * total_width)
  24. print(' ')
  25. return

参考资料

python3-cookbook-1.4-查找最大或最小元素

详解Python中heapq模块的用法(这里有实现show_tree的函数代码)

理解堆和堆排序的文章1

理解堆和堆排序的文章2

理解堆和堆排序的文章3

python奇技淫巧——max/min函数的用法

[PY3]——求TopN/BtmN 和 排序问题的解决的更多相关文章

  1. @NamedEntityGraphs --JPA按实体类对象参数中的字段排序问题得解决方法

    JPA按实体类对象参数中的字段排序问题得解决方法@Entity @Table(name="complaints") @NamedEntityGraphs({ @NamedEntit ...

  2. 第2节 网站点击流项目(下):3、流量统计分析,分组求topN

    四. 模块开发----统计分析 select * from ods_weblog_detail limit 2;+--------------------------+---------------- ...

  3. js关于对象键值为数字型时输出的对象自动排序问题的解决方法

    一.对象键值为数字型时输出的对象自动排序问题如: var objs = {    "1603":{id:"1603"},    "1702" ...

  4. Hadoop学习之路(二十)MapReduce求TopN

    前言 在Hadoop中,排序是MapReduce的灵魂,MapTask和ReduceTask均会对数据按Key排序,这个操作是MR框架的默认行为,不管你的业务逻辑上是否需要这一操作. 技术点 MapR ...

  5. [LeetCode]LRU Cache有个问题,求大神解答【已解决】

    题目: Design and implement a data structure for Least Recently Used (LRU) cache. It should support the ...

  6. hive求TopN语句

    ROW_NUMBER,RANK(),DENSE_RANK() 先了解这三个之间的区别: Rank():1,2,2,4,5(一般用这个较多,不会影响总排名) Dense_rank():1,2,2,3,4 ...

  7. sicily 1046. Plane Spotting(排序求topN)

    DescriptionCraig is fond of planes. Making photographs of planes forms a major part of his daily lif ...

  8. SQL分组求每组最大值问题的解决方法收集 (转载)

    例如有一个表student,其结构如下: id      name     sort      score 1        张三      语文      82 2        李四      数 ...

  9. 生成ansible-playbook的yaml文件的代码(字典排序问题无法解决)

    import yaml import collections def add_task(): return None def add_vars(): return None def add_handl ...

随机推荐

  1. 关于dm-file-uploader(dmUploader)上传时传参

    官网:https://github.com/danielm/uploaderDemo Online https://danielmg.org/demo/java-script/uploader/bas ...

  2. System Workbench for STM32(based on Eclipse)开发环境配置

    导入现有项目 不能有同名项目,即使不是同一目录 编译 根目录的Debug目录是编译时自动生成的.另外如果项目使用了git,那么编译时会自动在根目录生成一个.gitignore文件,把Debug目录排除 ...

  3. Windows上编译Boost

    Boost做得很好,有自己的build系统,可以几乎一键式编译,这才是尼玛世界一流质量的良心开源库啊. 将Boost 1.49.0解压到boost/boost_1_49_0里面,然后在boost目录底 ...

  4. form表单 相同name 多个value 的后台接受问题

    使用ajax序列化传到后台. data : $("#formid").serialize(); public void fun(@Valid Vo vo){} 使用vo的数组字段属 ...

  5. 对Java意义重大的7个性能指标

      本文中,小编搜集了7个最有影响的衡量标注,让你可以不依赖日志文件来了解应用程序现在,让我们看看这些性能指标,并了解如何查看并收集它们.: 一,响应时间和吞吐量 根据应用程序的响应时间可以知道程序完 ...

  6. MySQL开启日志记录查询/执行过的SQL语句

    作为后端开发者,遇到数据库问题的时候应该通过分析SQL语句来跟进问题所在,该方法可以记录所有的查询/执行的SQL语句到日志文件. 方法有几种,但是个人觉得以下这种最简单,但是重启MySQL服务后需要重 ...

  7. 如何构建debian包

        1)安装dh_make如下: sudo apt-get intasll aptitude sudo aptitude install dh_make    2)以jsoncpp为例,说明如何生 ...

  8. linux安装报错之:ifconfig command not found解决

    问题描述: 用虚拟机VMware安装linux系统(镜像文件是从官网下载的CentOS-7.0-1406-x86_64-DVD.iso), 在安装完成之后,输入ifconfig命令报错:ifconfi ...

  9. QTREE5 - Query on a tree V(LCT)

    题意翻译 你被给定一棵n个点的树,点从1到n编号.每个点可能有两种颜色:黑或白.我们定义dist(a,b)为点a至点b路径上的边个数. 一开始所有的点都是黑色的. 要求作以下操作: 0 i 将点i的颜 ...

  10. is 与 == 的区别;小数据池; 编码与解码

    1, is 与 == 的区别 ==  比较的是两边的值 is   比较的是两边的地址  id () 2,小数据池(在终端中) 数字小数据池的范围 -5 ~ 256 字符串中如果有特殊字符他们的内存地址 ...