## 2012年7月9日 星期一

### [ Python 文章收集 ] Sorting Mini-HOW TO

Preface :
Python lists 有內建的 sort() 函數提供 in-place 的排序 ; 另外在 Python 內建函數也有提供 sorted() API 可以提供用來排序現有的 list (但不改變它), 並建立一個新的 sorted list. 底下將對這兩種 sorting 的使用方法進行說明與介紹.

Sorting Basics :

>>> orig_list = [5, 2, 3, 1, 4]
>>> sort_list = sorted(orig_list)
>>> orig_list
[5, 2, 3, 1, 4] # sorting 後, 原先的 list 不會改變
>>> sort_list
[1, 2, 3, 4, 5]

>>> orig_list
[5, 2, 3, 1, 4]
>>> orig_list.sort() # 返回 None
>>> orig_list
[1, 2, 3, 4, 5]

Key Functions :

>>> sorted("This is a test staring from Alice".split(), key=str.lower)
['a', 'Alice', 'from', 'is', 'staring', 'test', 'This']
>>> sorted("This is a test staring from Alice".split()) # 如果沒有忽略大小寫, 大寫會排到小寫前面.
['Alice', 'This', 'a', 'from', 'is', 'staring', 'test']

>>> student_tuples = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
>>> sorted(student_tuples, key=lambda student: student[2]) # sort by age
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

Operator Module Functions :

>>> from operator import itemgetter, attrgetter
>>> sorted(student_tuples, key=itemgetter(2))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
>>> sorted(student_objects, key=attrgetter('age'))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

>>> sorted(student_tuples, key=itemgetter(1,2))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
>>> sorted(student_objects, key=attrgetter('grade', 'age'))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]

Ascending and Descending :

>>> sorted(student_tuples, key=itemgetter(2), reverse=True)
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
>>> sorted(student_objects, key=attrgetter('age'), reverse=True)
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]

Sort Stability and Complex Sorts :

>>> data = [('red', 1), ('blue', 1), ('red', 2), ('blue', 2)]
>>> sorted(data, key=itemgetter(0))
[('blue', 1), ('blue', 2), ('red', 1), ('red', 2)]

(Notice how the two records for 'blue' retain their original order so that ('blue', 1) is guaranteed to precede ('blue', 2).

>>> student_objects
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
>>> s = sorted(student_objects, key=attrgetter('age'))
>>> s
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
>>> sorted(s, key=attrgetter('grade'), reverse=True)
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

(The Timsort algorithm used in Python does multiple sorts efficiently because it can take advantage of any ordering already present in a dataset.

The Old Way Using the cmp Parameter :

1. def cmp_to_key(mycmp):
2.     'Convert a cmp= function into a key= function'
3.     class K(object):
4.         def __init__(self, obj, *args):
5.             self.obj = obj
6.         def __lt__(self, other):
7.             return mycmp(self.obj, other.obj) < 0
8.         def __gt__(self, other):
9.             return mycmp(self.obj, other.obj) > 0
10.         def __eq__(self, other):
11.             return mycmp(self.obj, other.obj) == 0
12.         def __le__(self, other):
13.             return mycmp(self.obj, other.obj) <= 0
14.         def __ge__(self, other):
15.             return mycmp(self.obj, other.obj) >= 0
16.         def __ne__(self, other):
17.             return mycmp(self.obj, other.obj) != 0
18.     return K

Supplement :
Understanding Python iterable and iterator

## 關於我自己

Where there is a will, there is a way!