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的Django框架中生成CSV文件的方法
Jul 22 Python
pycharm安装图文教程
May 02 Python
浅谈Python生成器generator之next和send的运行流程(详解)
May 08 Python
python获取外网IP并发邮件的实现方法
Oct 01 Python
浅谈python中字典append 到list 后值的改变问题
May 04 Python
python爬虫之urllib3的使用示例
Jul 09 Python
Python 通过微信控制实现app定位发送到个人服务器再转发微信服务器接收位置信息
Aug 05 Python
python实现递归查找某个路径下所有文件中的中文字符
Aug 31 Python
详解Python模块化编程与装饰器
Jan 16 Python
scrapy-splash简单使用详解
Feb 21 Python
python通配符之glob模块的使用详解
Apr 24 Python
python脚本框架webpy的url映射详解
Nov 20 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
php 判断页面或图片是否经过gzip压缩的方法
2017/04/05 PHP
PDO::quote讲解
2019/01/29 PHP
Laravel 实现Controller向blade前台模板赋值的四种方式小结
2019/10/22 PHP
Firefox div高度自适应
2009/04/28 Javascript
Javascript Web Slider 焦点图示例源码
2013/10/10 Javascript
js与jQuery 获取父窗、子窗的iframe
2013/12/20 Javascript
js格式化时间和js格式化时间戳示例
2014/02/10 Javascript
json的定义、标准格式及json字符串检验
2014/05/11 Javascript
jquery图片切换实例分析
2015/04/15 Javascript
JS实现当前页居中分页效果的方法
2015/06/18 Javascript
浅谈angularJS 作用域
2015/07/05 Javascript
javascript超过容器后显示省略号效果的方法(兼容一行或者多行)
2016/07/14 Javascript
JS实现的表头列头固定页面功能示例
2017/01/10 Javascript
深入浅出webpack教程系列_安装与基本打包用法和命令参数详解
2017/09/10 Javascript
Vue引入jquery实现平滑滚动到指定位置
2018/05/09 jQuery
深入浅出理解JavaScript高级定时器原理与用法
2018/08/02 Javascript
jQuery easyui datagird编辑行删除行功能的实现代码
2018/09/20 jQuery
vue安装遇到的5个报错及解决方法
2019/06/12 Javascript
[01:08:57]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS LGD第二场
2014/05/24 DOTA
[03:49]辉夜杯现场龙骑士COSER秀情商“我喜欢芬队!”
2015/12/27 DOTA
[04:44]DOTA2 2017全国高校联赛视频回顾
2017/08/21 DOTA
Pycharm远程调试openstack的方法
2017/11/21 Python
Python Pillow Image Invert
2019/01/22 Python
python简单贪吃蛇开发
2019/01/28 Python
Python3中编码与解码之Unicode与bytes的讲解
2019/02/28 Python
python仿抖音表白神器
2019/04/08 Python
python生成器用法实例详解
2019/11/22 Python
python plt可视化——打印特殊符号和制作图例代码
2020/04/17 Python
简单的HTML5初步入门教程
2015/09/29 HTML / CSS
Collection和Collections的区别
2016/05/02 面试题
医药大学生求职简历的自我评价
2013/10/17 职场文书
质量提升方案
2014/06/16 职场文书
工商管理专业毕业生自我鉴定2014
2014/10/04 职场文书
大学军训通讯稿
2015/07/18 职场文书
2016幼儿园毕业感言
2015/12/08 职场文书
三十年再续同学情倡议书
2019/11/27 职场文书