python-collections
python-collections
总述
Python数据结构常用模块:collections
、heapq
、operator
、itertools
高性能容器数据类型
import collections
print(collections.__all__)
['deque', 'defaultdict', 'namedtuple', 'UserDict', 'UserList',
'UserString', 'Counter', 'OrderedDict', 'ChainMap']
模块 | 说明 | |
---|---|---|
1 | Counter |
字典的子类,提供了可哈希对象的计数功能 |
2 | deque |
类似列表(list)的容器,实现了在两端快速添加(append)和弹出(pop) |
3 | OrderedDict |
字典的子类,保存了他们被添加的顺序 |
4 | defaultdict |
字典的子类,提供了一个工厂函数,为字典查询提供一个默认值 |
5 | namedtuple |
创建命名元组子类的工厂函数 |
6 | ChainMap |
类似字典(dict)的容器类,将多个映射集合到一个视图里面 |
7 | UserDict |
封装了字典对象,简化了字典子类化 |
8 | UserList |
封装了列表对象,简化了列表子类化 |
9 | UserString |
封装了列表对象,简化了字符串子类化 |
1-Counter计数器
计数器,继承于 dict
, 用于计算 hashtable
Counter
类的目的是用来跟踪统计值出现的次数,无序数据类型
以键值对的形式存储,
其中元素作为key,其计数作为value
#统计词频
colors = ['red', 'blue', 'red', 'green', 'blue', 'blue']
result = {}
for color in colors:
if result.get(color)==None:
result[color]=1
else:
result[color]+=1
print (result)
#{'red': 2, 'blue': 3, 'green': 1}
# 下面是Counter 的使用方法
from collections import Counter
colors = ['red', 'blue', 'red', 'green', 'blue', 'blue']
c = Counter(colors)
print (dict(c))
创建
collections.Counter([iterable-or-mapping])
# 支持传入 list,tuple,dict, str 等 iterable or mapping 类型
c = Counter() # 创建一个空的Counter类
c = Counter('gallahad') # 可iterable对象<list、tuple、dict、字符串>
c = Counter({'a': 4, 'b': 2}) # 从一个 dict 对象创建
c = Counter(a=4, b=2) # 从一组键值对创建
# Counter对象有一个字典接口,如果引用的键没有任何记录,就返回一个0
c = Counter(['eggs', 'ham'])
c['apple']=0
属性和方法
方法 | 描述 | ||
---|---|---|---|
most_common(n) |
从高到低的排序,返回前n 个元素,返回[('':5),('':3),..] |
||
elements() |
返回迭代器,Counter 内所有元素 |
||
update(counter) |
不同于dict这里values值是计数加法而不是覆盖,直接更新无返回值 | ||
substract(cout) |
和update类似,update是做加法,substract是对values计数减法 | ||
items() |
|||
keys() |
|||
values() |
#-----------------------------------------------------------\
#element
c = Counter(a=4, b=2, c=0, d=-2)
print(list(c.elements()))
#['a', 'a', 'a', 'a', 'b', 'b']
print(list(c.elements()))
#['a', 'a', 'a', 'a', 'b', 'b', 'd', 'd', 'd', 'd', 'd']
#-----------------------------------------------------------
#most_common()
count=Counter('abracadabra')
print(count.most_common())
#[('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]
print(count.most_common(n=3)) # 前3个
#[('a', 5), ('b', 2), ('r', 2)]
#-----------------------------------------------------------
#update([iterable-or-mapping]) 可以是 list str dict
count=Counter([1,2,3,4,5,1,3,2,])
print(cout)
#Counter({1: 2, 2: 2, 3: 2, 4: 1, 5: 1})
count.update([3, 1, 4, 5, 1])
print(count)
#Counter({1: 4, 3: 3, 2: 2, 4: 2, 5: 2, 7: 1})
#-----------------------------------------------------------
#subtract()
cout1 = Counter(a=4, b=2, c=0, d=-2)
cout2 = Counter(a=1, b=2, c=3, d=4)
print(cout1)
cout1.subtract(cout2)
print(cout1)
#Counter({'a': 4, 'b': 2, 'c': 0, 'd': -2})
#Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})
cout3 = Counter('aabbccdde')
cout4 = Counter('abcd')
print(cout3)
cout3.subtract(cout4)
print(cout3)
#Counter({'a': 2, 'b': 2, 'c': 2, 'd': 2, 'e': 1})
#Counter({'a': 1, 'b': 1, 'c': 1, 'd': 1, 'e': 1})
#-----------------------------------------------------------
#相互之间的数据集合操作
c = Counter(a=3, b=1, c=5)
d = Counter(a=1, b=2, d=4)
c+d counter相加,相同 key的value 相加
c-d counter相减,相同 key的value 相减
c&d 交集 取c,d两者中 value 取值小的那个
c|d 并集 取c,d两个中 value 取值大的那个
c = Counter(a=3, b=1)
d = Counter(a=1, b=2)
f1=c+d
print(f1)
f2=c-d
print(f2)
#Counter({'a': 4, 'b': 3})
#Counter({'a': 2})
#-----------------------------------------------------------
其他dict属性
c = Counter(a=5,b=4,c=3)
c.items() # dict items()
c.keys() # dict keys()
c.values()
c['a'] = 5 # dict 获取元素
c.get('a')=5 # 获取元素
del c['c'] # dict 删除元素
c.pop()
c.clear()
2-deque队列
dqueue 是 ”double-ended queue” 的简称, deque属于高性能的数据结构之一
双端队列(deque)具有从任一端添加和删除元素的功能
它的操作很像list 同时
相比于list实现的队列,deque实现拥有更低的时间和空间复杂度。list实现在出队(pop)和插入(insert)时的空间复杂度大约为O(n),deque在出队(pop)和入队(append)时的时间复杂度是O(1)。
所以deque更有优越性 而且deque既可以表示队列
创建
from collections import deque
d = deque()
属性和方法
方法 | 描述 | ||
---|---|---|---|
append() |
添加元素到右端 | ||
appendleft() |
左端 | ||
extend() |
添加iterable 对象到右端 |
||
extendleft() |
左端,结果中iterable 参数中的顺序将被反过来添加 |
||
insert() |
在位置 i 插入 x 。 | ||
pop() |
移去并且返回一个元素,最右端 | ||
popleft() |
移去并且返回一个元素,最左端 | ||
rotate(n=1) |
向右循环移动 n 步。 如果 n 是负数,就向左循环 | ||
maxlen |
Deque的最大尺寸,如果没有限定的话就是 None, 无括号 | ||
reverse() |
反转 | ||
remove(value) |
移除找到的第一个 value | ||
index() |
返回索引位置,不存在则ValueError |
||
count() |
计算 deque 中元素等于 x 的个数 | ||
clear() |
|||
copy() |
#--------------------------------------------------------
#apppend appendleft
dp=deque(list(range(6)))
dp.append(5)
print(dp)
dp.appendleft(-5)
print(dp)
#deque([0, 1, 2, 3, 4, 5, 5])
#deque([-5, 0, 1, 2, 3, 4, 5, 5])
#-------------------------------------------------------
#expend expendleft
dp2=deque(list(range(6)))
dp2.extend(list(range(8,11)))
print(dp2)
dp2.extendleft([1,2,3,4])
print(dp2)
#deque([0, 1, 2, 3, 4, 5, 8, 9, 10])
#deque([4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 8, 9, 10])
##-------------------------------------------------------
#pop popleft
dp2=deque(list(range(8)))
res1=dp2.pop()
res2=dp2.popleft()
print(dp2,',',res1,res2)
#deque([1, 2, 3, 4, 5, 6]) , 7 0
##-------------------------------------------------------
# remove
a = deque('abca')
a.remove('a')
print(a)
#deque(['b', 'c', 'a'])
##-------------------------------------------------------
#rotate()
dp2=deque(list(range(8)))
print(dp2)
dp2.rotate(3)
print(dp2)
#deque([0, 1, 2, 3, 4, 5, 6, 7])
#deque([5, 6, 7, 0, 1, 2, 3, 4])
##-------------------------------------------------------
d=deque(maxlen=10)
for i in range(20):
d.append(i)
print(d)
# deque([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
##-------------------------------------------------------
d = deque('xiaoweuge-shuai')
print(d.count('a'))
2
3-OrderedDict
OrderedDict 是字典的子类,保证了元素的插入顺序。在 3.7 版本下,字典同样也保证了元素的插入顺序。那相比内置字典 OrderedDict 有哪些升级呢
-
OrderedDict
继承dict
-
常规的
dict
被设计为非常擅长映射操作。 跟踪插入顺序是次要的 -
OrderedDict
旨在擅长重新排序操作。 空间效率、迭代速度和更新操作的性能是次要的 -
OrderedDict
类有一个move_to_end()
方法,可以有效地将元素移动到任一端。
属性方法 | 描述 | |
---|---|---|
popitem() |
移除并返回一个 (key, value) 键值对 | |
move_to_end(key) |
把指定键值对移动到最后 | |
clear ,fromkeys ,get |
其他继承方法 | |
items ,keys ,pop ,update ,values |
其他继承方法x |
创建
import collections
dic = collections.OrderedDict()
dic['k1'] = 'v1'
dic['k2'] = 'v2'
dic['k3'] = 'v3'
print(dic)
#输出:OrderedDict([('k1', 'v1'), ('k2', 'v2'), ('k3', 'v3')])
属性和方法
fromkeys()
fromkyes(iter,value)
# 由 序列 构造 字典 key 值不同,value 相同
"""
输入参数
iter 序列,list,tuple
value value的值
"""
dict=dict()
seq = [1,2,3]
dict = dict.fromkeys(seq,"icom")
print(dict)
{1: 'icom', 2: 'icom', 3: 'icom'}
##-------------------------------------------------------
d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}
d = OrderedDict(d)
print(d)
res=d.popitem()
print(res)
print(d)
#OrderedDict([('banana', 3), ('apple', 4), ('pear', 1), ('orange', 2)])
#('orange', 2)
#OrderedDict([('banana', 3), ('apple', 4), ('pear', 1)])
##-------------------------------------------------------
d = OrderedDict([('a', 'A'), ('b', 'B'), ('c', 'C')])
print(d)
d.move_to_end('b')
print(d)
#OrderedDict([('a', 'A'), ('b', 'B'), ('c', 'C')])
#OrderedDict([('a', 'A'), ('c', 'C'), ('b', 'B')])
4-defaultdict
返回一个新的类似字典的对象。 defaultdict是内置dict类的子类。它重载了一个方法并添加了一个可写的实例变量
一个需求案例
将(键-值对组成的)序列转换为(键-列表组成的)字典
data = [("p", 1), ("p", 2), ("p", 3),
("h", 1), ("h", 2), ("h", 3)]
转换成 result = {'p': [1, 2, 3], 'h': [1, 2, 3]}
#方法一
result = {}
for (key, value) in data:
if key in result:
result[key].append(value)
else:
result[key] = [value]
##-------------------------------------------------------
#方法二
result = {}
data = [("p", 1), ("p", 2), ("p", 3),
("h", 1), ("h", 2), ("h", 3)]
for (key, value) in data:
result.setdefault(key, []).append(value)
print(result)#'p': [1, 2, 3], 'h': [1, 2, 3]}
##-------------------------------------------------------
#方法三
from collections import defaultdict
result = defaultdict(list)
data = [("p", 1), ("p", 2), ("p", 3),
("h", 1), ("h", 2), ("h", 3)]
for (key, value) in data:
result[key].append(value)
print(result)
#defaultdict(<class 'list'>, {'p': [1, 2, 3], 'h': [1, 2, 3]})
##-------------------------------------------------------
# defaultdict(list) 使用list方法
s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
dic = defaultdict(list)
for i in s:
dic[i[0]].append(i[1])
dic = dict(dic)
print(dic)
for i in dic:
dic[i] = sum(dic[i])
print(dic)
#{'yellow': [1, 3], 'blue': [2, 4], 'red': [1]}
#{'yellow': 4, 'blue': 6, 'red': 1}
##-------------------------------------------------------
#defaultdict(set) 使用set 方法
s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('red', 1), ('blue', 4)]
d = defaultdict(set)
for k, v in s:
d[k].add(v)
print(d)
defaultdict(<class 'set'>, {'red': {1, 3}, 'blue': {2, 4}})
5-namedtuple
namedtuple
(typename, field_names, rename=False, defaults=None, module=None)
返回一个新的元组子类,名为 typename 。这个新的子类用于创建类元组的对象,可以通过字段名来获取属性值,同样也可以通过索引和迭代获取值
from collections import namedtuple
# 定义命名元组类:Point
# 创建的是一个类,需要进行实例化
Point = namedtuple('Point', ['x', 'y'])
p = Point(11, y=22)
print(p)
print(p[0],p[1],'11+22=',p[0]+p[1])
x,y=p
print(p.x*p.y)
#Point(x=11, y=22)
#11 22 11+22= 33
#242
属性方法 | 描述 | |
---|---|---|
_make() |
类方法从存在的序列或迭代实例创建一个新实例 | |
_asdict() |
返回一个新的 dict ,它将字段名称映射到它们对应的值 | |
_replace(**kwargs) |
返回一个新的命名元组实例,并将指定域替换为新的值 | |
_fields |
从现有元组创建一个新的命名元组类型 | |
_field_defaults |
映射默认值 |
Point = namedtuple('Point', ['x', 'y'])
p = Point(11, y=22)
t = [22, 44]
p1=Point._make(t)
print(p1)
p2=p1._asdict()
print(p2)
#Point(x=22, y=44)
#{'x': 22, 'y': 44}
p = Point(x=11, y=22)
p3=p._replace(x=55)
print(p3)
#Point(x=55, y=22)
#----------------------------------------------------------
Point = namedtuple('Point', ['x', 'y'])
print(p._fields)
Color = namedtuple('Color', 'red green blue')
Pixel = namedtuple('Pixel', Point._fields + Color._fields)
pix=Pixel(11, 22, 128, 255, 0)
print(pix)
#('x', 'y')
#Pixel(x=11, y=22, red=128, green=255, blue=0)
Account = namedtuple('Account', ['type', 'balance'], defaults=[0])
Account._field_defaults
print(Account._field_defaults)
acc=Account('premium')
print(acc)
#{'balance': 0}
#Account(type='premium', balance=0)
6-ChainMap-映射链
为了将多个映射快速的链接到一起,这样它们就可以作为一个单元处理
dcic1 = {'label1': '11', 'label2': '22'}
dcic2 = {'label2': '22', 'label3': '33'}
dcic3 = {'label4': '44', 'label5': '55'}
last = ChainMap(dcic1, dcic2,dcic3)
print(last)
# ChainMap({'label1': '11', 'label2': '22'}, {'label2': '22', 'label3': '33'}, {'label4': '44', 'label5': '55'})
方法 | 描述 | |
---|---|---|
maps |
返回映射 | |
new_child(m=None) |
返回一个新的ChainMap类,一个新映射(map),跟随当前实例的全部映射map | |
parents |
属性返回一个新的ChainMap包含所有的当前实例的映射,除了第一个 |
dcic1 = {'label1': '11', 'label2': '22'}
dcic2 = {'label1': '22', 'label2': '33'}
dcic3 = {'label4': '44', 'label5': '55'}
chain=ChainMap(dcic1, dcic2,dcic3)
print(chain)
print(chain.parents)
print(chain.maps)
print(list(chain))
#ChainMap({'label1': '11', 'label2': '22'}, {'label1': '22', 'label2': '33'}, {'label4': '44', 'label5': '55'})
#ChainMap({'label1': '22', 'label2': '33'}, {'label4': '44', 'label5': '55'})
#[{'label1': '11', 'label2': '22'}, {'label1': '22', 'label2': '33'}, {'label4': '44', 'label5': '55'}]
#['label4', 'label5', 'label1', 'label2']
#---------------------------------------------------------
chain.new_child(m={'key_new':888})
print(chain)
#ChainMap({'label1': '11', 'label2': '22'}, {'label1': '22', 'label2': '33'}, {'label4': '44', 'label5': '55'})