從序列中移除重復(fù)項(xiàng)且保持元素間順序不變
方法
可以用集合和生成器來(lái)解決
先來(lái)了解下什么是可哈希(hashable):
如果一個(gè)對(duì)象在自己的生命周期中有一哈希值(hash value)是不可改變的法绵,那么它就是可哈希的(hashable)的。可哈希對(duì)象是對(duì)象有hash(self)內(nèi)置函數(shù)的對(duì)象飞盆。對(duì)于可哈希的對(duì)象執(zhí)行這個(gè)函數(shù)將會(huì)返回一個(gè)整數(shù)沦零∑瓴剩可哈希對(duì)象判斷相等的唯一條件就是兩者的哈希值相等舰褪。Python中所有不可改變的的對(duì)象(imutable objects)都是可哈希的急黎,比如字符串健提,元組琳猫,也就是說(shuō)可改變的容器如字典,列表不可哈希(unhashable)私痹。我們用戶(hù)所定義的類(lèi)的實(shí)例對(duì)象默認(rèn)是可哈希的(hashable)脐嫂,它們都是唯一的统刮,而hash值也就是它們的id()。
t = (1, 2, 3)
s = '123'
l = [1,2,3]
d = [{'a': 1},{'b':2}]
print(t.__hash__())
print(s.__hash__())
print(l.__hash__) # list不是可哈希的
print(l[1].__hash__()) # list的對(duì)象可哈希
print(d.__hash__) # dict不是可哈希的
# set(d) # 列表的元素是字典账千,字典是不可哈希的侥蒙,所以返回TypeError: unhashable type: 'dict'
print(set([(1,2), (1,2), (2,)])) # 列表的元素是元組,元組是可哈希的
2528502973977326415
-8527273320470595707
None
2
None
{(1, 2), (2,)}
# 當(dāng)序列中的元素是可哈希時(shí)
def dedupe(items):
seen = set()
for item in items:
if item not in seen:
yield item
seen.add(item)
a= [1, 5, 2, 1, 7, 5, 9 ,0]
b = set(a)
c = dedupe(a)
print(b)
print(list(c))
{0, 1, 2, 5, 7, 9}
[1, 5, 2, 7, 9, 0]
# 當(dāng)不確定序列中的元素是否可哈希時(shí)匀奏,需要對(duì)程序改造如下
def dedupe(items, key=None):
seen = set()
for item in items:
val = item if key is None else key(item)
if val not in seen:
yield item
seen.add(val)
a= [{'x':1, 'y':2}, {'x':1, 'y':3}, {'x':1, 'y':2}, {'x':2, 'y':4}]
# b = set(a) # a的元素是字典鞭衩,字典不是可哈希的,所以返回TypeError: unhashable type: 'dict'
c = dedupe(a, key=lambda d: (d['x'], d['y']))
d = dedupe(a, key=lambda d: (d['x']))
print(list(c))
print(list(d))
[{'y': 2, 'x': 1}, {'y': 3, 'x': 1}, {'y': 4, 'x': 2}]
[{'y': 2, 'x': 1}, {'y': 4, 'x': 2}]
# 讀取一個(gè)文件娃善,去除其中的重復(fù)行
with open('a.txt', 'r') as f:
# print(list(f)) # ['abc\n', 'a\n', 'df\n', 'abc\n', 'df\n', '123\n']
print(list(dedupe(f))) # ['abc\n', 'a\n', 'df\n', '123\n']
['abc\n', 'a\n', 'df\n', '123\n']
找出序列中出現(xiàn)次數(shù)最多的元素
方法
可以用collections模塊中的Counter類(lèi)來(lái)實(shí)現(xiàn)
Counter的底層是一個(gè)字典论衍,在元素和它們出現(xiàn)的次數(shù)間做了一個(gè)映射。Counter對(duì)象提供任何可哈希的對(duì)象序列作為輸入聚磺。
from collections import Counter
words = ['a', 'a', 'b', 'a', 'e', 'f', 'a', 'e', 'e', 'd', 'd']
count = Counter(words)
print(count)
print(count.most_common(3)) # 出現(xiàn)次數(shù)最多的前三個(gè)元素
Counter({'a': 4, 'e': 3, 'd': 2, 'f': 1, 'b': 1})
[('a', 4), ('e', 3), ('d', 2)]
print(count['f'])
count['f'] += 1 # 還可以手動(dòng)增加某個(gè)元素的出現(xiàn)次數(shù)
print(count['f'])
1
2
print(count)
words_2 = ['b', 'a', 'c']
count.update(words_2) # update方法可以更新count的數(shù)據(jù)
print(count)
Counter({'a': 8, 'e': 6, 'd': 4, 'f': 3, 'b': 2})
Counter({'a': 9, 'e': 6, 'd': 4, 'f': 3, 'b': 3, 'c': 1})
# Counter對(duì)象的各種運(yùn)算
a = Counter(words)
b = Counter(words_2)
print(a)
print(b)
print(a + b)
print(a- b)
Counter({'a': 4, 'e': 3, 'd': 2, 'f': 1, 'b': 1})
Counter({'c': 1, 'b': 1, 'a': 1})
Counter({'a': 5, 'e': 3, 'b': 2, 'd': 2, 'f': 1, 'c': 1})
Counter({'a': 3, 'e': 3, 'd': 2, 'f': 1})
對(duì)字典列表的排序
friends = [
{'name': 'jlan', 'age': 27, 'gender': 'm'},
{'name': 'lann', 'age': 25, 'gender': 'f'},
{'name': 'bob', 'age': 23, 'gender': 'm'},
{'name': 'herry', 'age': 28, 'gender': 'f'},
{'name': 'dairy', 'age': 26, 'gender': 'm'}
]
print(friends)
from operator import itemgetter
print(sorted(friends, key=itemgetter('age')))
print(sorted(friends, key=itemgetter('age', 'name')))
# itemgetter()的參數(shù)可以是字典的鍵坯台、用數(shù)字表示的列表元素等任何可以穿給對(duì)象的__getitem__()方法的值。
# 用lambda也可以實(shí)現(xiàn)這樣的功能瘫寝,但是用itemgetter通常效率更高
print(sorted(friends, key=lambda f: f['age']))
print(sorted(friends, key=lambda f: (f['age'], f['name'])))
[{'gender': 'm', 'age': 27, 'name': 'jlan'}, {'gender': 'f', 'age': 25, 'name': 'lann'}, {'gender': 'm', 'age': 23, 'name': 'bob'}, {'gender': 'f', 'age': 28, 'name': 'herry'}, {'gender': 'm', 'age': 26, 'name': 'dairy'}]
[{'gender': 'm', 'age': 23, 'name': 'bob'}, {'gender': 'f', 'age': 25, 'name': 'lann'}, {'gender': 'm', 'age': 26, 'name': 'dairy'}, {'gender': 'm', 'age': 27, 'name': 'jlan'}, {'gender': 'f', 'age': 28, 'name': 'herry'}]
[{'gender': 'm', 'age': 23, 'name': 'bob'}, {'gender': 'f', 'age': 25, 'name': 'lann'}, {'gender': 'm', 'age': 26, 'name': 'dairy'}, {'gender': 'm', 'age': 27, 'name': 'jlan'}, {'gender': 'f', 'age': 28, 'name': 'herry'}]
[{'gender': 'm', 'age': 23, 'name': 'bob'}, {'gender': 'f', 'age': 25, 'name': 'lann'}, {'gender': 'm', 'age': 26, 'name': 'dairy'}, {'gender': 'm', 'age': 27, 'name': 'jlan'}, {'gender': 'f', 'age': 28, 'name': 'herry'}]
[{'gender': 'm', 'age': 23, 'name': 'bob'}, {'gender': 'f', 'age': 25, 'name': 'lann'}, {'gender': 'm', 'age': 26, 'name': 'dairy'}, {'gender': 'm', 'age': 27, 'name': 'jlan'}, {'gender': 'f', 'age': 28, 'name': 'herry'}]
# key=itemgetter()或lambda方法同樣也可以用于min蜒蕾,max之類(lèi)的函數(shù)
根據(jù)字段將記錄分組
用itertools.groupby()方法
from operator import itemgetter
from itertools import groupby
# 字符串壓縮,面試經(jīng)常會(huì)出現(xiàn)這樣的問(wèn)題
l = 'aabbbbcccddeddff'
for key, group in groupby(l):
print(key)
print(list(group))
a
['a', 'a']
b
['b', 'b', 'b', 'b']
c
['c', 'c', 'c']
d
['d', 'd']
e
['e']
d
['d', 'd']
f
['f', 'f']
friends = [
{'name': 'jlan', 'age': 27, 'gender': 'm'},
{'name': 'lann', 'age': 25, 'gender': 'f'},
{'name': 'bob', 'age': 23, 'gender': 'm'},
{'name': 'herry', 'age': 28, 'gender': 'f'},
{'name': 'dairy', 'age': 26, 'gender': 'm'}
]
# 對(duì)friends按性別分組
friends.sort(key=itemgetter('gender'))
for key, group in groupby(friends, key=itemgetter('gender')):
print(key)
print(list(group))
f
[{'gender': 'f', 'age': 25, 'name': 'lann'}, {'gender': 'f', 'age': 28, 'name': 'herry'}]
m
[{'gender': 'm', 'age': 27, 'name': 'jlan'}, {'gender': 'm', 'age': 23, 'name': 'bob'}, {'gender': 'm', 'age': 26, 'name': 'dairy'}]
說(shuō)明
groupby()方法通過(guò)掃描序列找出擁有相同值(或是由參數(shù)key指定的函數(shù)返回的值)的序列項(xiàng)焕阿,并將它們分組咪啡。groupby()創(chuàng)建了一個(gè)迭代器,每次迭代都返回一個(gè)值(分組的key)和一個(gè)子迭代器(屬于該分組的group)捣鲸。對(duì)與friends這樣序列如果要按照性別分組瑟匆,需要先對(duì)friends按性別進(jìn)行排序,把相同性別的項(xiàng)放在一塊栽惶,然后才能按groupby()進(jìn)行分組愁溜。