collections模块常用拓展数据类型

一、collections模块简介

除内置数据类型(dict、list、set、tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter、deque、defaultdict、namedtuple和OrderedDict等。
(1)namedtuple: 生成可以使用名字来访问元素内容的tuple
(2)deque: 双端队列,可以快速的从另外一侧追加和推出对象
(3)Counter: 计数器,主要用来计数
(4)OrderedDict: 有序字典
(5)defaultdict: 带有默认值的字典

1. namedtuple的用法

我们知道tuple可以表示不变集合,例如,一个点的三维坐标就可以表示成:

p = (1, 2, 5)
print(p)

但是,看到(1, 2,5),很难看出这个tuple是用来表示一个三维坐标的。
此时,namedtuple就派上了用场:

from collections import namedtuple

# namedtuple('名称', [属性list]):

Point = namedtuple('Point', ['x', 'y', 'z'])
p = Point(1, 2, 5)
print(p)
print(p.x, p.y, p.z)

2. deque的用法

使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低。
deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:

from collections import deque

q = deque(['Lawrence', '小梁', '小黑', '小白'])
q.append('小黄')  # 默认添加在右侧尾部
print(q)
q.appendleft('Python3')
print(q)

deque除了实现list的append()和pop()外,还支持appendleft()和popleft(),这样就可以非常高效地往头部添加或删除元素。

q.pop()  # 从尾部删除
q.popleft()  # 从头部删除,不能传值
print(q)

3. OrderedDict的用法

使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序。
   如果要保持Key的顺序,可以用OrderedDict:

from collections import OrderedDict

d = dict([('name', 'Lawrence'), ('age', 18), ('sex', '男'), ('id', '1141400030')])

print(d)  # dict的Key是无序的
{'name': 'Lawrence', 'age': 18, 'sex': '男', 'id': '1141400030'}
od = OrderedDict([('name', 'Lawrence'), ('age', 18), ('sex', '男'), ('id', '1141400030')])

print(od)  # OrderedDict的Key是有序的

# OrderedDict([('name', 'Lawrence'), ('age', 18), ('sex', '男'), ('id', '1141400030')])

print(od['age'])  # 获取key对应的值内容

注意:OrderedDict的Key会按照插入的顺序排列,不是Key本身排序

from collections import OrderedDict

od = OrderedDict()
od['name'] = 'Lawrence'
od['age'] = 18
od['work'] = '清洁工'
od['id'] = 1141440030
print(od.keys())  # 按照插入的Key的顺序返回

# 结果:odict_keys(['name', 'age', 'work', 'id'])

4. defaultdict的用法

有如下值集合 [16, 26, 46, 36, 66, 56, 76, 86, 96, 6…],将所有大于 66 的值保存至字典的第一个key中,将小于 66 的值保存至第二个key的值中。
即: {‘k1’: 大于66 , ‘k2’: 小于66}
  方式一:原生字典解决方法

values = [16, 26, 46, 36, 66, 56, 76, 86, 96, 6]

my_dict = {'k1': [], 'k2': []}

for value in values:
    if value > 66:
        if value in my_dict['k1']:
            break
        else:
            my_dict['k1'].append(value)
    else:
        if value in my_dict['k2']:
            break
        else:
            my_dict['k2'].append(value)
            
print(my_dict)

方式二:defaultdict字典解决方法

from collections import defaultdict

values = [16, 26, 46, 36, 66, 56, 76, 86, 96, 6]

my_dict = defaultdict(list)
for value in values:
    if value > 66:
        my_dict['k1'].append(value)
    else:
        my_dict['k2'].append(value)
        
print(my_dict)

# 结果:defaultdict(<class 'list'>, {'k2': [16, 26, 46, 36, 66, 56, 6], 'k1': [76, 86, 96]})

使用dict时,如果引用的Key不存在,就会抛出KeyError。如果希望key不存在时,返回一个默认值,就可以用defaultdict:

from collections import defaultdict

d = defaultdict(lambda: 'N/A')
d['name'] = 'Lawrence'
d['name']  # name存在 返回具体值:'Lawrence'

print(d['age'])  # age不存在,返回默认值

4. Counter的用法

Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。计数值可以是任意的Interger(包括0和负数)

from collections import Counter

c = Counter(['Lawrence', '小黑', '小梁', '小白', '小红', '小梁', 'Lawrence', 'Chloe', '小黑','小梁'])
print(c)  

# 结果:Counter({'小梁': 3, 'Lawrence': 2, '小黑': 2, '小白': 1, '小红': 1, 'Chloe': 1})

创建
下面的代码说明了Counter类创建的四种方法:
  Counter类的创建

from collections import Counter

c1 = Counter()  # 创建一个空的Counter类
c2 = Counter('iterable')  # 从一个可iterable对象(list、tuple、dict、字符串等)创建
c3 = Counter({'a': 4, 'b': 2, 'c': 5})  # 从一个字典对象创建
c4 = Counter(a=4, b=2, c=5)  # 从一组键值对创建

计数值的访问与缺失的键
当所访问的键不存在时,返回0,而不是KeyError;否则返回它的计数。
计数值的访问

from collections import Counter

c = Counter(['Lawrence', '小黑', '小梁', '小白', '小红', '小梁', 'Lawrence', 'Chloe', '小黑', '小梁'])
print(c.keys())  # dict_keys(['Lawrence', '小黑', '小梁', '小白', '小红', 'Chloe'])
print(c.values())  # dict_values([2, 2, 3, 1, 1, 1])
print(c['小蓝'])  # 没有返回0

计数器的更新(update和subtract)
可以使用一个iterable对象或者另一个Counter对象来更新键值。
计数器的更新包括增加和减少两种。其中
增加使用update()方法:
  计数器的更新(update)

from collections import Counter

c = Counter('which')
c.update('where')  # 使用另一个iterable对象更新
print(c['h'])
print(c)
d = Counter('watch')
c.update(d)  # 使用另一个Counter对象更新
print(c['h'])
print(c)

减少则使用subtract()方法:
  计数器的更新(subtract)

from collections import Counter
c = Counter(['Lawrence', '小黑', '小红', '小白', '小红', '小梁', 'Lawrence', 'Chloe', '小黑', '小梁', '小黑'])
c.subtract(['小白'])  # 使用另一个iterable对象更新
print(c)  # Counter({'小黑': 3, 'Lawrence': 2, '小红': 2, '小梁': 2, 'Chloe': 1, '小白': 0})
d = Counter(['小蓝', '小红'])
c.subtract(d)  # 使用另一个Counter对象更新
print(c)  # Counter({'小黑': 3, 'Lawrence': 2, '小梁': 2, '小红': 1, 'Chloe': 1, '小白': 0, '小蓝': -1})

键的修改和删除
当计数值为0时,并不意味着元素被删除,删除元素应当使用del。
键的删除

from collections import Counter
c = Counter('abcddfscba')
print(c)
c['b'] = 0
print(c)
del c['a']
print(c)

elements()的用法
返回一个迭代器。元素被重复了多少次,在该迭代器中就包含多少个该元素。元素排列无确定顺序,个数小于1的元素不被包含。
elements()方法:

from collections import Counter
c = Counter(a=4, b=2, c=0, d=-2, e=7)
l_c = list(c.elements())  # ['a', 'a', 'a', 'a', 'b', 'b', 'e', 'e', 'e', 'e', 'e', 'e', 'e']
print(l_c)

most_common([n])
返回一个TopN列表。如果n没有被指定,则返回所有元素。当多个元素计数值相同时,排列是无确定顺序的。
most_common()方法:

from collections import Counter

c = Counter('abracasdddabra')
print(c.most_common())
print(c.most_common(3))

# 结果:

# [('a', 5), ('d', 3), ('b', 2), ('r', 2), ('c', 1), ('s', 1)]

# [('a', 5), ('d', 3), ('b', 2)]

浅拷贝copy

from collections import Counter

c = Counter('0311')
print(c)  # Counter({'1': 2, '0': 1, '3': 1})
d = c.copy()
print(d)  # Counter({'1': 2, '0': 1, '3': 1})

算术和集合操作
+、-、&、|操作也可以用于Counter。其中&和|操作分别返回两个Counter对象各元素的最小值和最大值。需要注意的是,得到的Counter对象将删除小于1的元素。
Counter对象的算术和集合操作

from collections import Counter

c = Counter(a=3, b=1)
d = Counter(a=1, b=4)
print(c + d)  # c[x] + d[x]

# Counter({'b': 5, 'a': 4})

print(c - d)  # subtract(只保留正数计数的元素)

# Counter({'a': 2})

print(c & d)  # 交集:  min(c[x], d[x])

# Counter({'a': 1, 'b': 1})

print(c | d)  # 并集:  max(c[x], d[x])

# Counter({'b': 4, 'a': 3})

其他常用操作
下面是一些Counter类的常用操作,来源于Python官方文档
Counter类常用操作

list(c)  # 将c中的键转为列表
set(c)  # 将c中的键转为set
dict(c)  # 将c中的键值对转为字典
c.items()  # 转为(elem, cnt)格式的列表
Counter(dict(list_of_pairs))  # 从(elem, cnt)格式的列表转换为Counter类对象
c.most_common()[:-n:-1]  # 取出计数最少的n个元素
c += Counter()  # 移除0和负值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值