Google's Python Class(四)——Python 排序

原文:https://developers.google.com/edu/python/sorting

最简单的排序方式是调用 sorted(list) 函数,该函数以一个 list 为参数,返回一个按顺序排序号的新的 list。原来的 list 不会改变。

  a = [5, 1, 4, 3]
  print sorted(a)  ## [1, 3, 4, 5]
  print a  ## [5, 1, 4, 3]

通常都会将一个 list 传进 sorted() 函数,但是实际上该函数的参数可以是任何一种可遍历的集合。下面会介绍另一个比较老的 list.sort() 函数。而 sorted() 函数似乎比 sort() 函数更容易使用,所以我推荐使用 sorted()。

sorted() 函数可以通过可选的参数进行客制化。例如,sorted() 的可选参数 reverse=True,sorted(list, reverse=True) 表示反向排序。

  strs = ['aa', 'BB', 'zz', 'CC']
  print sorted(strs)  ## ['BB', 'CC', 'aa', 'zz'] (case sensitive)
  print sorted(strs, reverse=True)   ## ['zz', 'aa', 'CC', 'BB']

使用 key= 自定义排序

对于更加复杂的自定义排序,sorted() 所带的 “key=” 可选参数指定了一个在比较之前用于转换每个元素的 “key” 函数。这个 key 函数带有一个值并且返回一个值,返回的“代理”值用于排序的比较。

例如:一个字符串列表,指定 key=len(内置的 len() 函数)来根据字符串的长度,从短到长进行排序。每个字符串调用 len() 得到各自代理长度值的 list,然后对这些代理值进行排序。

  strs = ['ccc', 'aaaa', 'd', 'bb']
  print sorted(strs, key=len)  ## ['d', 'bb', 'ccc', 'aaaa']

另一个例子,指定 “str.lower” 作为 key 函数,强制将大写和小写当成一样(忽略大小写)进行排序:

  ## "key" argument specifying str.lower function to use for sorting
  print sorted(strs, key=str.lower)  ## ['aa', 'BB', 'CC', 'zz']

你也可以将自己定义的 MyFn 作为 key 函数传进 sorted() 中,例如:

  ## Say we have a list of strings we want to sort by the last letter of the string.
  strs = ['xc', 'zb', 'yd' ,'wa']

  ## Write a little function that takes a string, and returns its last letter.
  ## This will be the key function (takes in 1 value, returns 1 value).
  def MyFn(s):
    return s[-1]

  ## Now pass key=MyFn to sorted() to sort by the last letter:
  print sorted(strs, key=MyFn)  ## ['wa', 'zb', 'xc', 'yd']

想要使用 key= 自定义排序,需要记住你要提供一个函数,该函数传进一个值并返回一个引导排序的代理值。sorted() 还有一个可选的参数 “cmp=cmpFn”,该参数指定一个两个参数的比较函数,该比较函数传进 list 的两个值并且返回 negative/0/positive 来指明排序的顺序。对于 strings、ints 等,内置的比较函数是 cmp(a, b),所以我们经常会在比较器中调用 cmp()。对于 “cmp=cmpFn” 参数,较新的 key= 参数排序通常会更适合。

sort() 方法

作为 sorted() 的替代函数,list 的 sort() 方法将 list 递增排序,如 list.sort()。sort() 方法会改变原来的 list 并返回 None,因此按照如下的方法使用 sort():

  alist.sort()            ## correct
  alist = blist.sort()    ## NO incorrect, sort() returns None

上面是使用 sort() 时经常会犯的错误——它不会返回排好序的列表。sort() 方法必须由一个列表调用;它不能用于任何可列举集合(但是上述的 sorted() 函数对于任何集合都可以使用)。sort() 方法早于 sorted() 函数,因此你很可能在一些比较老的代码中看到 sort() 方法。sort() 方法不需要创建一个新的列表,所以对于要排序的元素已经在一个列表中的情况,sort() 方法会快一点。

元组

元组是一个固定大小的元素分组,例如一个 (x,y) 坐标。元组与列表一样,只是元组是不可变的和不能改变大小的(元组并不是严格的不可变,因为它所包含的其中一个元素是可变的)。元组在 Python 中起到一种 “struct” 的作用——一种方便的方法,用来传递少量逻辑、固定大小的一捆值。一个需要返回多个值的函数可以返回一个包含值的元组。例如,如果我想要一个三维坐标的列表,正常 Python 表达方式是一个包含元组的列表,该列表中每个元组是一个大小为 3 的 (x, y, z) 分组。

将值放在以逗号隔开的小括号中来创建一个元组。“空”元组就是一对空的小括号。访问元组里面的元素跟访问列表的一样——len()、[ ]、for、in等。

  tuple = (1, 2, 'hi')
  print len(tuple)  ## 3
  print tuple[2]    ## hi
  tuple[2] = 'bye'  ## NO, tuples cannot be changed
  tuple = (1, 2, 'bye')  ## this works

对于创建一个大小为 1 的元组,要在单独的元素后面加上一个逗号

  tuple = ('hi',)   ## size-1 tuple

这对于语法来说是一种有趣的情况,但是逗号是必须的,它用于区分元组和将表达式放入小括号的情况。在一些情况下你可以省略小括号,Python 会根据逗号来判断你想要的是一个元组。将一个元组赋值给一个同等大小由变量名组成的元组相当于将所有对应的值赋值到变量中。如果两个元组大小不一样,那么会报错。列表也有这个特性。

  (x, y, z) = (42, 13, "hike")
  print z  ## hike
  (err_string, err_code) = Foo()  ## Foo() returns a length-2 tuple

列表推导(可选)

列表推导是一个比较高级的特性,该特性在某些情况下是很好用的,但是在练习中没必要用到,并且在刚开始学习的时候也不需要涉及到(也就是说你可以跳过这一部分)。一个列表推导是一种简洁的方法来写可以展开成一个完整列表的表达式。假设我们有一个列表 [1, 2, 3, 4],下面是列表推导计算该列表平方 [1, 4, 9, 16] 的代码:

  nums = [1, 2, 3, 4]

  squares = [ n * n for n in nums ]   ## [1, 4, 9, 16]

[ expr for var in list ] 语法中的 for var in list 看起来像一个常规的不带冒号(:)的 for 循环。每个元素计算一次 expr,并将结果传给新的列表。下面是一个字符串的例子,该例子中将每个字符串字母变成大写,并在后面添加 ‘!!!’:

  strs = ['hello', 'and', 'goodbye']

  shouting = [ s.upper() + '!!!' for s in strs ]
  ## ['HELLO!!!', 'AND!!!', 'GOODBYE!!!']

你可以在 for 循环的右边添加一个 if 检查来过滤结果。每个元素都会计算 if 检查,剩下 if 语句返回为 True 的元素。

  ## Select values <= 2
  nums = [2, 8, 1, 6]
  small = [ n for n in nums if n <= 2 ]  ## [2, 1]

  ## Select fruits containing 'a', change to upper case
  fruits = ['apple', 'cherry', 'bannana', 'lemon']
  afruits = [ s.upper() for s in fruits if 'a' in s ]
  ## ['APPLE', 'BANNANA']

练习:list1.py

尝试使用排序和元组来解决 google-python-exerciseslist1.py 的问题(位于 basic/ 目录下)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值