从序列中移除重复项并且保持元素间的顺序不变
在前面,我们学习了如何在两个字典中找到共同点,那么当我们找到共同点的时候想从这个序列中移除重复项并想保持元素间的顺序不变的时候就需要用到集合和生成器来进行解决,就像这样:
def dedupe(items):
seen = set()
for item in items:
if item not in seen
yield item
seen.add(item)
但是请注意:用集合和生成器的方法仅限于序列中的值是可哈希的,也就是说,这个列表里的所有函数都必须满足以下三个条件:支持hash函数,也就是实现hash方法。这个方法的返回值在对象的生命周期里永远不变
支持相等判断,也就是实现eq方法
如果a == b, 那么hash(a)一定等于hash(b),也就是相等的对象,哈希值一定相等
如果你想在不可哈希对象的序列中去除重复项,代码应该是这个样子的:
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)
key的作用是指定一个函数用来将序列中的元素转换为可哈希的类型,这样就可以检测重复项
对切片命名
有时候我们的代码变得乱糟糟的无法阅读,到处都是切片索引,这个时候我们需要清理一下。
假设有一些代码是用来从字符串的固定位置中取出具体数据:
###### 012345678901234567890123456789012345678901234567890‘
record = '.......................100..........513.25..............'
cost = int(record[20:32]) * float(record[40:48])
与其这样,还不如对切片命名:
SHARES = slice(20, 32)
PRICE = slice(40, 48)
cost = int(record[20:32]) * float(record[40:48])
作为一条基本准则,代码中如果有很多硬编码的索引值,将导致可读性和可维护性都会下降。一般来说,内置的slice()函数会创建一个切片对象可以用于任何允许进行切片操作的地方
此外,可以通过使用indices(size)的方法将切片映射到特定的大小的序列上,这样就会返回一个(start, stop, step)元组,所有的值都已经恰当地限制在边界以内。
找出序列中出现次数最多的元素
假设有一个元素序列,如果我们想知道在序列中出现次数最多的元素的时候,我们就需要用到collections模块中的Counter类了。
这么说吧,假设我们有一个列表,列表中是一系列的单词,我们想找出哪些单词出现得最频繁,就可以这样:
def most_freqency():
words = [
'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes',
'the', 'eyes', 'the', 'eyes', 'the', 'eyes', 'not', 'around', 'the',
'eyes', "don't", 'look', 'around', 'the', 'eyes', 'look', 'into',
'my', 'eyes', "you're", 'under'
]
from collections import Counter
word_counts = Counter(words)
# 出现频率最高的3个单词
top_three = word_counts.most_common(3)
print(top_three)
# Outputs [('eyes', 8), ('the', 5), ('look', 4)]
if __name__ == '__main__':
most_freqency()
实际上,我们可以给Counter对象提供任何可哈希对象序列作为输入。在底层实现中,Counter是一个字典,在元素和它们出现的次数间做了映射。
参考书目:
《Python CookBook》作者:【美】 David Beazley, Brian K. Jones
Github地址:yidao620c/python3-cookbookgithub.com