collections----------容器数据类型

1.Counters作为一个容器,可以跟踪相同的值增加了多少次。这个类可以用来实现其他语言中常用包(bag)或多集合(multiset)数据结构来实现的算法。

初始化

  Counter支持3中形式的初始化。调用Counter的构造函数时可以提供一个元素序列或者一个包含键和计数的字典,还可以使用关键字参数将字符串名映射到计数。

import collections

print(collections.Counter(['a','b','c','a','b','c']))
print(collections.Counter({'a':2,'b':3,'c':1}))
print(collections.Counter(a=2,b=3,c=1))

  如果不提供任何参数,可以构造一个空Counter,然后通过update()方法填充。

import collections
c = collections.Counter()
print('Interval :',c)
c.update('abcdaab')
print('Sequence', c)
c.update({'a':1,'d':5})

  计数值将根据新数据增加,替换数据不会改变计数。

Interval : Counter()
Sequence Counter({'a': 3, 'b': 2, 'c': 1, 'd': 1})
Dict: Counter({'d': 6, 'a': 4, 'b': 2, 'c': 1})

  

访问计数

  一旦填充了Counter,可以使用字典API获取他的值。

c = collections.Counter('abcdaab')
for letter in 'abcde':
    print('%s : %d' % (letter, c[letter]))

  对未知的元素,Counter不会产生KeyError。如果在输入中没有找到某个值(如此例中的e),其计数为0。

a : 3
b : 2
c : 1
d : 1
e : 0

  elements()方法返回一个迭代器,将生成Counter知道的所有元素。

c = collections.Counter('extremely')
c['z']=  0
print(c)
print(list(c.elements()))

  不能保证元素的顺序不变,另外计数小于或等于0的元素不包含在内。

Counter({'e': 3, 'x': 1, 't': 1, 'r': 1, 'm': 1, 'l': 1, 'y': 1, 'z': 0})
['e', 'e', 'e', 'x', 't', 'r', 'm', 'l', 'y']

  使用most_common()可以生成一个序列,其中包含n个最常遇到的输入值及其相应计数。

c = collections.Counter()
with open('words.text', 'rt') as f:
    for line in f:
        c.update(line.rstrip().lower())
print('Most common:')
for letter,count in c.most_common(3):
    print('%s : %7d' % (letter, count))

  这个例子要统计系统的所有单词出现的字母,来生成一个频度分布,然后打印3个最常见的字母。如果不向most_common()提供参数,会生成成所有元素构成一个列表。按照频度排列。

Most common:
o :      15
j :      12
d :      10

算数操作

  Counter实例支持算数和集合操作来完成结果的聚集。

c1 = collections.Counter(['a','b','c','a','b','b'])
c2 = collections.Counter('alphabet')
print('C1:',c1)
print('C2:',c2)
print('\nCombined counts:')
print(c1 + c2)
print('\nSubtraction:')
print(c1 - c2)
print('\nIntersection (taking positive minimums):')
print(c1 & c2)
print('\nUnion (taking maximums):')
print(c1 | c2)

  每次通过一个操作生成一个新的Counter时,计数为0或负数的元素都会被删除。在c1和c2中a的计数相同,所以减法操作后他的计数为0.

C1: Counter({'b': 3, 'a': 2, 'c': 1})
C2: Counter({'a': 2, 'l': 1, 'p': 1, 'h': 1, 'b': 1, 'e': 1, 't': 1})

Combined counts:
Counter({'a': 4, 'b': 4, 'c': 1, 'l': 1, 'p': 1, 'h': 1, 'e': 1, 't': 1})

Subtraction:
Counter({'b': 2, 'c': 1})

Intersection (taking positive minimums):
Counter({'a': 2, 'b': 1})

Union (taking maximums):
Counter({'b': 3, 'a': 2, 'c': 1, 'l': 1, 'p': 1, 'h': 1, 'e': 1, 't': 1})

  

2.defaultdict。标准字典包括一个方法setdefault()来获取一个值,如果这个值不存在则建立一个默认值。与之相反,defaultdict初始化容器是会让调用者提前指定默认值。

def default_factory():
    return 'default value'
d = collections.defaultdict(default_factory,foo = 'bar')
print('d', d)
print('foo =>', d['foo'])
print('bar =>', d['bar'])

  只要所有键都有相同的默认值并无不妥。就可以使用这个方法。如果默认值是一种用于聚集或累加值的类型,如:list,set或者甚至是int,这个方法尤其有用。

d defaultdict(<function default_factory at 0x00000000024F9DC8>, {'foo': 'bar'})
foo => bar
bar => default value

  

3.deque。(双端队列)支持从任意一段增加和删除元素。更为常用的两种结构,即栈和队列,就是双端队列的退化形式,其输入和输出限制在一段。

d = collections.deque('abcdefg')
print('Deque:', d)
print('Length:', len(d))
print('Left end:', d[0])
print('Right end:', d[-1])
d.remove('c')
print('remove(c):', d)

  由于deque是一种序列容器,因此同样支持list的一些操作,如用__getitem__()检查内容,确定长度,以及通过匹配小时从序列中间删除元素。

Deque: deque(['a', 'b', 'c', 'd', 'e', 'f', 'g'])
Length: 7
Left end: a
Right end: g
remove(c): deque(['a', 'b', 'd', 'e', 'f', 'g'])

  

填充

  deque可以从任意一端填充,可以左端填充,和右端填充。

#Add to the right
d1 = collections.deque()
d1.extend('abcdefg')
print('extend:', d1)
d1.append('h')
print('append:', d1)
#Add to the left
d2 = collections.deque()
d2.extendleft(range(6))
print('extendleft:', d2)
d2.appendleft(6)
print('appendleft:', d2)

  extendleft()函数迭代处理其输入,对各个元素完成与appendleft()同样的处理。最终结果是deque将包含逆序的输入序列。

extend: deque(['a', 'b', 'c', 'd', 'e', 'f', 'g'])
append: deque(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
extendleft: deque([5, 4, 3, 2, 1, 0])
appendleft: deque([6, 5, 4, 3, 2, 1, 0])

  

利用

  类似地,可以从两端或任意一端利用deque的元素,这取决于所应用的算法。

print('From the right:')
d = collections.deque('abcdefg')
while True:
    try:
        print(d.pop())
    except IndexError:
        break
print('\nFrom the left:')
d = collections.deque(range(6))
while True:
    try:
        print(d.popleft())
    except IndexError:
        break

  使用pop(0可以从deque的右端删除一个元素。使用popleft()可以从deque的左端删除一个元素。

From the right:
g
f
e
d
c
b
a

From the left:
0
1
2
3
4
5

  由于双端队列是线程安全的,所以甚至可以在不同线程中同时从两端利用队列的内容。

 

 

 

 

 

 

 

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

 

上一篇:STL——容器(deque) deque 的大小


下一篇:.net 操作excel