序列
-
刪除相同元素并保持序列順序
問題:*怎樣在一個序列上面保持元素順序的同時消除重復的值?
方案:- 利用集合,但是不維護序列的順序,無序
- 利用sorted() 、min()、max()等內置函數思想,自定義一個函數
#示例:使用集合:對結果的順序無要求,可以考慮
>>> list1=[1,3,4,3,4,2,1,8]
>>> set(list1)
{8, 1, 2, 3, 4}
>>> list3=[(1,2),(2,3),(1,2)]
>>> set(list3)
{(1, 2), (2, 3)}
>>>
?? 由上述例子可見,集合去掉重復元素后,不能保持原有的順序,這也是集合的特性。
?? 如果需要既要消除重復元素,又要維持序列原有的順序,可參考sorted()等內置函數的思想,結合集合自定義一個返回生成器的函數。
#示例1:列表去重并保持順序
>>> def dedup(items):
setp=set()
for i in items:
if i not in setp:
yield i
setp.add(i)
>>> dedup(list1)
<generator object dedup at 0x022AE330>
>>>#當結果足夠大時,盡量不要直接轉換成list,這里只是示例
>>> list(dedup(list1))
[1, 3, 4, 2, 8]
?? 如果序列的元素為字典類型呢?用上述方法不可用,理由是序列元素(字典)不屬于hashable類型,需要將字典變成hashable類型,換言之,將鍵值對轉化成元組形式。
引申概念
?? 什么是可哈希(hashable)的?一個 object 是可哈希的(hashable),是指這個 object 在其生存期內有一個不變的哈希值(hash value),即hash() 方法返回的值。
示例2:元素為字典類型的序列
>>> list1=[1,3,4,3,4,2,1,8]
>>> list2=[{'x':1,'y':2},{'x':1,'y':3},{'x':1,'y':5},{'x':1,'y':2}]
>>> def dedup(items,key=None):
setp=set()
for item in items:
val=item if key is None else key(item )
if val not in setp:
yield val
setp.add(val)
>>> list(dedup(list1))
[1, 3, 4, 2, 8]
>>> for i in dedup(list2,key=lambda x:(x['x'],x['y'])):
print(i)
(1, 2)
(1, 3)
(1, 5)
>>>
-
對象不支持原生的比較操作
問題:如果你想排序同類對象,但是元素的比較操作不支持直接比較?
方案:
?? 在類實例對象中,利用sorted()函數關鍵字參數key特性,可以傳入一個 callable 對象給它,這個 callable 對象對每個傳入的對象返回一個值,這個值會被 sorted 用來排序這些對象。
?? key對應函數的實現
?? ?? - lambda匿名函數實現
?? ?? - operator模塊attrgetter()函數實現,支持多個字段進行排序。用法類似用于字典的operator.itemgetter()
#示例
>>> from operator import attrgetter
>>> class User:
def __init__(self,user_id):
self.user_id=user_id
def __repr__(self):
return 'User({})'.format(self.user_id)
>>> users = [User(23), User(3), User(99)]
>>> users
[User(23), User(3), User(99)]
>>> sorted(users,key=lambda user:user.user_id)
[User(3), User(23), User(99)]
>>> sorted(users,key=attrgetter('user_id'))
[User(3), User(23), User(99)]
>>>
總結
?? 數據結構與算法這一章節基本學習結束,大部分內容基本理解,少部分內容不甚理解,待后續學習的深入,再回頭看看。通過最近每天學習一點點,最大的感受是豁然開朗:思路更開闊,想法更多。回顧以前寫的腳本或者正在寫的腳本,仍有很多地方需要改善,怎么讓代碼更優雅、更簡潔、可讀、不重復造輪子,仍然值得進一步思考。