Python中对元组和列表按条件进行排序的方法示例


Posted in Python onNovember 10, 2015

在python中对一个元组排序

我的同事Axel Hecht 给我展示了一些我所不知道的关于python排序的东西。 在python里你可以对一个元组进行排序。例子是最好的说明:

>>> items = [(1, 'B'), (1, 'A'), (2, 'A'), (0, 'B'), (0, 'a')]
>>> sorted(items)
[(0, 'B'), (0, 'a'), (1, 'A'), (1, 'B'), (2, 'A')]

默认情况下内置的sort和sorted函数接收的参数是元组时,他将会先按元组的第一个元素进行排序再按第二个元素进行排序。 然而,注意到结果中(0, 'B')在(0, 'a')的前面。这是因为大写字母B的ASCII编码比a小。然而,假设你想要一些更人性的排序并且不关注大小写。你或许会这么做:

>>> sorted(items, key=str.lower)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: descriptor 'lower' requires a 'str' object but received a 'tuple'

我们将会得到一个错误,因为他不能正确处理元组的第一部分。(注:原文作者估计想说元组中第一项是数字,不能使用lower这个方法;正确的原因提示的很明显了,是因为你传递的是一个元组,而元组是没有lower这个方法的)

我们可以试着写一个lambda函数(eg.sorted(items, key=lambda x: x.lower() if isinstance(x, str) else x)),他将不会工作因为你只处理了元组的一个元素。(注:同上面,作者这么做必然是错的,思考给这个lambda传一个元组,返回的是什么?)

言归正传,下面就是你应该怎么做的方法。一个lambda,它会返回一个元组:

>>> sorted(items, key=lambda x: (x[0], x[1].lower()))
[(0, 'a'), (0, 'B'), (1, 'A'), (1, 'B'), (2, 'A')]

现在你完成了它!谢谢Axel的分享!

我确信你知道你可以倒序排列,仅仅使用sorted(items, reverse=True, …),但是你怎么根据关键字来进行不同的排序?

使用lambda函数返回元组的技巧,下面是一个我们排序一个稍微高级的数据结构:

>>> peeps = [{'name': 'Bill', 'salary': 1000}, {'name': 'Bill', 'salary': 500}, {'name': 'Ted', 'salary': 500}]

现在,使用lambda函数返回一个元组的特性来排序:

>>> sorted(peeps, key=lambda x: (x['name'], x['salary']))
[{'salary': 500, 'name': 'Bill'}, {'salary': 1000, 'name': 'Bill'}, {'salary': 500, 'name': 'Ted'}]

很有意思,对吧?Bill 在Ted的前面,并且500在1000的前面。但是如何在相同的 name 下,对 salary 反向排序?很简单,对它取反:

>>> sorted(peeps, key=lambda x: (x['name'], -x['salary']))
[{'salary': 1000, 'name': 'Bill'}, {'salary': 500, 'name': 'Bill'}, {'salary': 500, 'name': 'Ted'}]

问题:将列表[[1, 2, 3], [4, 5, 6], [7, 8, 9]]排序为[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
分析:

1.转变过程如下:

1 2 3          1 4 7
4 5 6   —> 2 5 8
7 8 9          3 6 9

可以将变换过程看成是原二维数组行(row)变成新数组的列(column),即抽出原数组第一行(row)作为第一列(column),第二行(row)作为第二列(column)…当然也可以将变换过程看成是原数组的列变为新数组的行,限于时间,就暂不考虑这种实现方式。
2.最原始的做法,写两个for循环,外层循环依次迭代数组的行(row),内层循环迭代数组的列(column),来实现这个反转过程,将原数组第一行(row)作为第一列(column),第二行(row)作为第二列(column),过程如下:

In [7]: l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

In [8]: len_row = 3

In [9]: len_col = 3

In [10]: temp = [[],[],[]]

In [11]: for row in l:
  ....:   for i in range(len_col):
  ....:     temp[i].append(row[i])
  ....:   print temp
  ....:
[[1], [2], [3]]
[[1, 4], [2, 5], [3, 6]]
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

In [12]:

当然,还可以使用列表推导来做,原理和上面一样,外层迭代row,内层迭代col,生成新的列表:

In [100]: l
Out[100]: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

In [101]: [[row[col] for row in l] for col in range(len(l[0])) ]
Out[101]: [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

最后,对这个题目,用zip也可以达到同样的目的:

In [104]: l
Out[104]: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

In [105]: zip(*l)
Out[105]: [(1, 4, 7), (2, 5, 8), (3, 6, 9)]

In [106]: map(list,zip(*l))
Out[106]: [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

*这个符号和列表配合有解压的意思,如l=[[1, 2, 3], [4, 5, 6], [7, 8, 9]],则我理解*l就变成了[1, 2, 3], [4, 5, 6], [7, 8, 9]这样三个值,所以zip(*l)和zip([1, 2, 3], [4, 5, 6], [7, 8, 9])的结果才会是一样的,如下:

In [17]: l=[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

In [18]: zip([1, 2, 3], [4, 5, 6], [7, 8, 9])
Out[18]: [(1, 4, 7), (2, 5, 8), (3, 6, 9)]

In [19]: zip(*l)
Out[19]: [(1, 4, 7), (2, 5, 8), (3, 6, 9)]

In [20]:
Python 相关文章推荐
使用Python写个小监控
Jan 27 Python
Python简单连接MongoDB数据库的方法
Mar 15 Python
Python轻量级ORM框架Peewee访问sqlite数据库的方法详解
Jul 20 Python
对pandas读取中文unicode的csv和添加行标题的方法详解
Dec 12 Python
python实现彩色图转换成灰度图
Jan 15 Python
Python基于Logistic回归建模计算某银行在降低贷款拖欠率的数据示例
Jan 23 Python
Python这样操作能存储100多万行的xlsx文件
Apr 16 Python
Python实现通过解析域名获取ip地址的方法分析
May 17 Python
python选取特定列 pandas iloc,loc,icol的使用详解(列切片及行切片)
Aug 06 Python
python 爬取百度文库并下载(免费文章限定)
Dec 04 Python
python pillow库的基础使用教程
Jan 13 Python
python实现高效的遗传算法
Apr 07 Python
Python 文件管理实例详解
Nov 10 #Python
Python list操作用法总结
Nov 10 #Python
python控制台中实现进度条功能
Nov 10 #Python
使用Python发送各种形式的邮件的方法汇总
Nov 09 #Python
尝试使用Python多线程抓取代理服务器IP地址的示例
Nov 09 #Python
使用Python实现BT种子和磁力链接的相互转换
Nov 09 #Python
Python中MySQLdb和torndb模块对MySQL的断连问题处理
Nov 09 #Python
You might like
真正面向对象编程:PHP5.01发布
2006/10/09 PHP
php开发工具之vs2005图解
2008/01/12 PHP
PHP中Header使用的HTTP协议及常用方法小结
2014/11/04 PHP
PHP判断是否是微信打开还是浏览器打开的方法
2019/02/27 PHP
JavaScript中void(0)的具体含义解释
2007/02/27 Javascript
javascript 写类方式之九
2009/07/05 Javascript
JQuery显示、隐藏div的几种方法简明总结
2015/04/16 Javascript
漫谈JS引擎的运行机制 你应该知道什么
2016/06/15 Javascript
JQuery遍历元素的父辈和祖先的方法
2016/09/18 Javascript
JavaScript编写九九乘法表(两种任选)
2017/02/04 Javascript
vue.js轮播图组件使用方法详解
2018/07/03 Javascript
vue实现动态显示与隐藏底部导航的方法分析
2019/02/11 Javascript
详解bootstrap-fileinput文件上传控件的亲身实践
2019/03/21 Javascript
轻松解决JavaScript定时器越走越快的问题
2019/05/13 Javascript
JavaScript Image对象实现原理实例解析
2020/08/26 Javascript
[02:36]DOTA2英雄基础教程 斯拉克
2013/11/29 DOTA
[01:15:56]2018DOTA2亚洲邀请赛3月30日 小组赛A组 TNC VS Newbee
2018/03/31 DOTA
python学习笔记之调用eval函数出现invalid syntax错误问题
2015/10/18 Python
Python 3.8 新功能全解
2019/07/25 Python
python数组循环处理方法
2019/08/26 Python
解决Python命令行下退格,删除,方向键乱码(亲测有效)
2020/01/16 Python
pytorch forward两个参数实例
2020/01/17 Python
Python 操作 PostgreSQL 数据库示例【连接、增删改查等】
2020/04/21 Python
Hotels.com中国区:好订网
2016/08/18 全球购物
英国最全面的橄榄球联盟门票网站:Live Rugby Tickets
2018/10/06 全球购物
高中语文教学反思
2014/01/16 职场文书
教学器材管理制度
2014/01/26 职场文书
《和我们一样享受春天》教学反思
2014/02/07 职场文书
竞选文艺委员演讲稿
2014/04/28 职场文书
2014年征兵标语
2014/06/20 职场文书
群众路线党员自我评议范文2014
2014/09/24 职场文书
反对四风自我剖析材料
2014/10/07 职场文书
党员作风建设自查报告
2014/10/23 职场文书
2014年英语教研组工作总结
2014/12/06 职场文书
请学会珍惜眼前,因为人生没有下辈子!
2019/11/12 职场文书
Nginx反爬虫策略,防止UA抓取网站
2021/03/31 Servers