(董付国)Python 学习笔记---Python序列(5)

再谈内置方法sorted()

  • 列表对象它提供了sort()方法支持原地排序,而内置函数sorted()返回一个新列表,并不对原列表进行任何修改。
  • sorted()方法可以对列表、元组、字典、range对象进行排序。
  • 列表的sort()和内置函数sorted()都支持key参数实现复杂排序要求。

(一)

persons = [{'name':'Dong','age':37},{'name':'Zhang','age':40},
           {'name':'Li','age':50},{'name':'Dong','age':43},
           {'name': 'Ai', 'age': 80}]
print(persons)

#使用key来指定排序依据,先按姓名升序排序,姓名相同的按年龄降序排序
print(sorted(persons,key = lambda x:(x['name'],-x['age'])))
[{'name': 'Dong', 'age': 37}, {'name': 'Zhang', 'age': 40}, {'name': 'Li', 'age': 50}, {'name': 'Dong', 'age': 43}, {'name': 'Ai', 'age': 80}]
[{'name': 'Ai', 'age': 80}, {'name': 'Dong', 'age': 43}, {'name': 'Dong', 'age': 37}, {'name': 'Li', 'age': 50}, {'name': 'Zhang', 'age': 40}]

(二)

phonebook = {'Linda':'7750','Bob':'9345','Carol':'5834'}
from operator import itemgetter
print(sorted(phonebook.items(),key = itemgetter(1)))#按字典中元素的值进行排序
print(sorted(phonebook.items(),key = itemgetter(0)))#按字典中元素的键进行排序
[('Carol', '5834'), ('Linda', '7750'), ('Bob', '9345')]
[('Bob', '9345'), ('Carol', '5834'), ('Linda', '7750')]

(三)

gameresult = [['Bob',95.0,'A'],['Alan',86.0,'C'],
              ['Mandy',83.5,'A'],['Rob',89.3,'E']]
from operator import itemgetter
print(sorted(gameresult,key = itemgetter(0,1))) #按姓名升序,姓名相同按分数升序排序
print(sorted(gameresult,key = itemgetter(1,0))) #按分数升序,分数相同按姓名升序排序
print(sorted(gameresult,key = itemgetter(2,0))) #按等级升序,等级相同按姓名升序排序
[['Alan', 86.0, 'C'], ['Bob', 95.0, 'A'], ['Mandy', 83.5, 'A'], ['Rob', 89.3, 'E']]
[['Mandy', 83.5, 'A'], ['Alan', 86.0, 'C'], ['Rob', 89.3, 'E'], ['Bob', 95.0, 'A']]
[['Bob', 95.0, 'A'], ['Mandy', 83.5, 'A'], ['Alan', 86.0, 'C'], ['Rob', 89.3, 'E']]

注:TypeError: XXX object is not callable问题有可能的原因

  1. 类型不匹配
  2. 参数个数不对

(四)

#列表里面是字典元素
gameresult = [{'name':'Bob','wins':10,'rating':75.0},
              {'name':'David','wins':3,'rating':57.0},
              {'name':'Carol','wins':4,'rating':57.0},
              {'name':'patty','wins':9,'rating':72.8},
              {'name':'James','wins':10,'rating':79}]      
from operator import itemgetter

#按wins升序,该值相同的按name升序排序
print(sorted(gameresult,key = itemgetter('wins','name')))
[{'name': 'David', 'wins': 3, 'rating': 57.0}, {'name': 'Carol', 'wins': 4, 'rating': 57.0}, {'name': 'patty', 'wins': 9, 'rating': 72.8}, {'name': 'Bob', 'wins': 10, 'rating': 75.0}, {'name': 'James', 'wins': 10, 'rating': 79}]
  • 根据另外一个列表的值来对当前列表元素进行排序
list1 = ["what","I'm","sorting","by"]
list2 = ["something","else","to","sort"]

pairs = zip(list1,list2)
pairs = sorted(pairs)
print('pairs = ',pairs)

result = [x[1] for x in pairs]
print('result = ',result)
pairs =  [("I'm", 'else'), ('by', 'sort'), ('sorting', 'to'), ('what', 'something')]
result =  ['else', 'sort', 'to', 'something']

1.6 复杂数据结构

  • 在解决实际问题时,还经常需要用到其他复杂的数据结构,如堆,栈,队列,树,图等等。
  • 有些结构Python已经提供,而有些则需要自己利用基本数据结构来实现。

1.6.1 堆

>>> import heapq                        #heapq和random是python标准库
>>> import random
>>> data = list(range(10))
>>> data
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> random.choice(data)                 #随机选择一个元素
5
>>> random.shuffle(data)                #随机打乱顺序
>>> data
[1, 3, 4, 5, 0, 8, 7, 2, 9, 6]
>>> heap = []
>>> for n in data:                      #建堆
...     heapq.heappush(heap,n)
...
>>> heap
[0, 1, 4, 2, 3, 8, 7, 5, 9, 6]
>>> #第i个元素的值小于第(2i+1和2i+2)个元素的值
...
>>>
>>> heapq.heappush(heap,0.5)            #入堆,自动重建
>>> heap
[0, 0.5, 4, 2, 1, 8, 7, 5, 9, 6, 3]
>>> heapq.heappop(heap)                 #出堆,自动重建
0
>>> myheap = [1,2,3,5,7,8,9,4,10,333]
>>> heapq.heapify(myheap)               #建堆
>>> myheap
[1, 2, 3, 4, 7, 8, 9, 5, 10, 333]
>>> heapq.heapreplace(myheap,6)         #弹出最小元素,同时插入新元素
1
>>> myheap
[2, 4, 3, 5, 7, 8, 9, 6, 10, 333]
>>> heapq.nlargest(3,myheap)            #返回前3个最大的元素
[333, 10, 9]
>>> heapq.nsmallest(3,myheap)           #返回前3个最小的元素
[2, 3, 4]

1.6.2 队列

  • 可以使用列表模拟队列(没办法控制大小)结构
>>> x = [1,2,3,4]
>>> x.pop(0)
1
>>> x.append(5)
>>> x
[2, 3, 4, 5]
>>> x.pop
<built-in method pop of list object at 0x000002B842A3B708>
>>> list(x)
[2, 3, 4, 5]
>>> x.pop(0)
2
>>> x
[3, 4, 5]
>>> x.pop(0)
3
>>> x.pop(0)
4
>>> x.pop(0)
5
>>> x.pop(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: pop from empty list
>>> import queue                #queue是Python标准库
>>> q = queue.Queue()
>>> q.put(0)                    #入队
>>> q.put(1)
>>> q.put(2)
>>> q.queue
deque([0, 1, 2])
>>> q.get()                     #出队,队列只能从一边进,另一头出
0
>>> q.get()
1
>>> q.queue
deque([2])

设置队列大小:

>>> import queue
>>> q = queue.Queue()
>>> q.get(timeout = 2)		#当等待2s后没有元素出来就判定为空,弹出异常
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    q.get(timeout = 2)		#当等待2s后没有元素出来就判定为空,弹出异常
_queue.Empty
>>> q = queue.Queue(3)		#我们可以空过设置size来设置队列长度
>>> q
<queue.Queue object at 0x000001FA6EEE8F08>
>>> q.queue
deque([])
>>> q.put(0)
>>> q.put(1)
>>> q.put(2)
>>> q.queue
deque([0, 1, 2])
>>> q.put(3)
  • queue模块还提供了“后进先出”队列和优先级队列
>>> from queue import Queue             #LIFO队列
>>> q = Queue()                         #创建队列对象
>>> q.put(0)                            #在队列尾部插入元素
>>> q.put(1)
>>> q.put(2)
>>> print(q.queue)                      #查看队列中所有元素
deque([0, 1, 2])
>>> q.get()                             #返回并删除队列头部元素
0
>>> q.get()
1
>>> from queue import LifoQueue         #Lifo队列
>>> q = LifoQueue()                     #创建LIFO队列对象
>>> q.put(0)
>>> q.put(1)
>>> q.put(2)
>>> q.queue                             #查看队列中所有元素
[0, 1, 2]
>>> q.get()
2
>>> q.get()
1
>>> q.get()
0
>>> q.get()                             #对空队列调用get()方法会阻塞当前线 程

优先级队列:

>>> from queue import PriorityQueue             #优先级队列
>>> q = PriorityQueue()                         #创建优先级队列对象
>>> q.put(3)                                    #插入元素)
>>> q.put(8)                                    #插入元素
>>> q.put(100)
>>> q.queue                                     #查看优先级队列中所有元素
[3, 8, 100]
>>> q.put(1)                                    #插入元素,自动调整优先级队列
>>> q.put(2)
>>> q.queue
[1, 2, 100, 8, 3]
>>> q.get()                                     #返回并删除优先级最低的元素
1
>>> q.get()                                     #请多执行几次该语句并观察返回的数据
2
>>> q.get()
3
>>> q.get()
8
>>> q.get()
100
>>> q.get()

  • Python标准库collections提供了双端队列deque
>>> from collections import deque
>>> q = deque(maxlen = 5)                       #创建双端队列
>>> for item in [3,5,7,9,11]:#添加元素
  File "<stdin>", line 1
    for item in [3,5,7,9,11]:#添加元素
                            ^
SyntaxError: invalid character in identifier
>>> from collections import deque
>>> q = deque(maxlen = 5)                       #创建双端队列
>>> for item in [3,5,7,9,11]:                   #添加元素
...     q.append(item)
...
>>> q.append(13)                                #队列满,自动溢出
>>> q,append(15)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'append' is not defined
>>> q.append(15)
>>> q
deque([7, 9, 11, 13, 15], maxlen=5)
>>> q.appendleft(5)                             #从左侧添加元素,右侧自动溢出
>>> q
deque([5, 7, 9, 11, 13], maxlen=5)

注:SyntaxError: invalid character in identifier
错误原因:没有变换输入法,导致“:”和“:”,占字符不一样。在注释 # 之前夹杂了中文输入法的空格,在print缩进也有同样错误!
解决方法:删掉注释前的空格即以后的注释即可

1.6.3 栈

  • 栈是一种“后进先出(LIFO)”或“先进后出(FILO)”的数据结构。
  • Python列表本身就可以实现栈结构的基本操作。例如,列表对象的append()方法是在列表尾部追加元素,类似于入栈操作;pop()方法默认是弹出并返回列表的最后一个元素,类似于出栈操作。
  • 但是直接使用Python列表对象模拟栈操作并不是很方便,例如当列表为空时,再执行pop()出栈操作时则会抛出一个很不友好的异常;另外,也无法限制栈的大小。
  • 可以直接使用列表来实现栈结构
>>> myStack = []
>>> myStack.append(3)
>>> myStack.append(5)
>>> myStack.append(7)
>>> myStack
[3, 5, 7]
>>> myStack.pop()
7
>>> myStack.pop()
5
>>> myStack.pop()
3
>>> myStack.pop()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: pop from empty list
posted @ 2019-08-09 13:15  旅人_Eric  阅读(145)  评论(0编辑  收藏  举报