collection模块是对专业的容器数据类型:

  • Counter(计数器):dict子类,用于计算可哈希性对象的个数。
  • OrderedDict(有序字典):dict 子类,记录着数据成员添加的顺序。
  • defaultdict(默认字典):调用一个工厂函数来为dict的values值缺失提供一个默认值。
  • namedtuple(可命名元组):工厂函数生成有命名字段的tuple子类。
  • deque(双向队列):能在“队列”两端快速出队、入队的函数,类似于队列的(list-like)的容器。
  • ChainMap:为多个映射创建单一视图的类字典类型。
  • 将字典包裹起来使得创建字典的子类更容易。
  • 将列表对象包裹起来使得创建列表的子类更容易
  • 将字符串对象包裹起来使得创建字符串的子类更容易。

参考网页:https://docs.python.org/3.5/library/collections.html

 

1.计数器(counter)

Counter类相似于bags或multisets等语言类。

它的元素从一个可迭代对象计数,或从另一个映射(或计数器)初始化。

  1 class Counter(dict):
  2     '''Dict subclass for counting hashable items.  Sometimes called a bag
  3     or multiset.  Elements are stored as dictionary keys and their counts
  4     are stored as dictionary values.
  5 
  6     >>> c = Counter('abcdeabcdabcaba')  # count elements from a string
  7 
  8     >>> c.most_common(3)                # three most common elements
  9     [('a', 5), ('b', 4), ('c', 3)]
 10     >>> sorted(c)                       # list all unique elements
 11     ['a', 'b', 'c', 'd', 'e']
 12     >>> ''.join(sorted(c.elements()))   # list elements with repetitions
 13     'aaaaabbbbcccdde'
 14     >>> sum(c.values())                 # total of all counts
 15     15
 16 
 17     >>> c['a']                          # count of letter 'a'
 18     5
 19     >>> for elem in 'shazam':           # update counts from an iterable
 20     ...     c[elem] += 1                # by adding 1 to each element's count
 21     >>> c['a']                          # now there are seven 'a'
 22     7
 23     >>> del c['b']                      # remove all 'b'
 24     >>> c['b']                          # now there are zero 'b'
 25     0
 26 
 27     >>> d = Counter('simsalabim')       # make another counter
 28     >>> c.update(d)                     # add in the second counter
 29     >>> c['a']                          # now there are nine 'a'
 30     9
 31 
 32     >>> c.clear()                       # empty the counter
 33     >>> c
 34     Counter()
 35 
 36     Note:  If a count is set to zero or reduced to zero, it will remain
 37     in the counter until the entry is deleted or the counter is cleared:
 38 
 39     >>> c = Counter('aaabbc')
 40     >>> c['b'] -= 2                     # reduce the count of 'b' by two
 41     >>> c.most_common()                 # 'b' is still in, but its count is zero
 42     [('a', 3), ('c', 1), ('b', 0)]
 43 
 44     '''
 45     # References:
 46     #   http://en.wikipedia.org/wiki/Multiset
 47     #   http://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html
 48     #   http://www.demo2s.com/Tutorial/Cpp/0380__set-multiset/Catalog0380__set-multiset.htm
 49     #   http://code.activestate.com/recipes/259174/
 50     #   Knuth, TAOCP Vol. II section 4.6.3
 51 
 52     def __init__(*args, **kwds):
 53         '''Create a new, empty Counter object.  And if given, count elements
 54         from an input iterable.  Or, initialize the count from another mapping
 55         of elements to their counts.
 56 
 57         >>> c = Counter()                           # a new, empty counter
 58         >>> c = Counter('gallahad')                 # a new counter from an iterable
 59         >>> c = Counter({'a': 4, 'b': 2})           # a new counter from a mapping
 60         >>> c = Counter(a=4, b=2)                   # a new counter from keyword args
 61 
 62         '''
 63         if not args:
 64             raise TypeError("descriptor '__init__' of 'Counter' object "
 65                             "needs an argument")
 66         self, *args = args
 67         if len(args) > 1:
 68             raise TypeError('expected at most 1 arguments, got %d' % len(args))
 69         super(Counter, self).__init__()
 70         self.update(*args, **kwds)
 71 
 72     def __missing__(self, key):
 73         'The count of elements not in the Counter is zero.'
 74         # Needed so that self[missing_item] does not raise KeyError
 75         return 0
 76 
 77     def most_common(self, n=None):
 78         '''List the n most common elements and their counts from the most
 79         common to the least.  If n is None, then list all element counts.
 80 
 81         >>> Counter('abcdeabcdabcaba').most_common(3)
 82         [('a', 5), ('b', 4), ('c', 3)]
 83 
 84         '''
 85         # Emulate Bag.sortedByCount from Smalltalk
 86         if n is None:
 87             return sorted(self.items(), key=_itemgetter(1), reverse=True)
 88         return _heapq.nlargest(n, self.items(), key=_itemgetter(1))
 89 
 90     def elements(self):
 91         '''Iterator over elements repeating each as many times as its count.
 92 
 93         >>> c = Counter('ABCABC')
 94         >>> sorted(c.elements())
 95         ['A', 'A', 'B', 'B', 'C', 'C']
 96 
 97         # Knuth's example for prime factors of 1836:  2**2 * 3**3 * 17**1
 98         >>> prime_factors = Counter({2: 2, 3: 3, 17: 1})
 99         >>> product = 1
100         >>> for factor in prime_factors.elements():     # loop over factors
101         ...     product *= factor                       # and multiply them
102         >>> product
103         1836
104 
105         Note, if an element's count has been set to zero or is a negative
106         number, elements() will ignore it.
107 
108         '''
109         # Emulate Bag.do from Smalltalk and Multiset.begin from C++.
110         return _chain.from_iterable(_starmap(_repeat, self.items()))
111 
112     # Override dict methods where necessary
113 
114     @classmethod
115     def fromkeys(cls, iterable, v=None):
116         # There is no equivalent method for counters because setting v=1
117         # means that no element can have a count greater than one.
118         raise NotImplementedError(
119             'Counter.fromkeys() is undefined.  Use Counter(iterable) instead.')
120 
121     def update(*args, **kwds):
122         '''Like dict.update() but add counts instead of replacing them.
123 
124         Source can be an iterable, a dictionary, or another Counter instance.
125 
126         >>> c = Counter('which')
127         >>> c.update('witch')           # add elements from another iterable
128         >>> d = Counter('watch')
129         >>> c.update(d)                 # add elements from another counter
130         >>> c['h']                      # four 'h' in which, witch, and watch
131         4
132 
133         '''
134         # The regular dict.update() operation makes no sense here because the
135         # replace behavior results in the some of original untouched counts
136         # being mixed-in with all of the other counts for a mismash that
137         # doesn't have a straight-forward interpretation in most counting
138         # contexts.  Instead, we implement straight-addition.  Both the inputs
139         # and outputs are allowed to contain zero and negative counts.
140 
141         if not args:
142             raise TypeError("descriptor 'update' of 'Counter' object "
143                             "needs an argument")
144         self, *args = args
145         if len(args) > 1:
146             raise TypeError('expected at most 1 arguments, got %d' % len(args))
147         iterable = args[0] if args else None
148         if iterable is not None:
149             if isinstance(iterable, Mapping):
150                 if self:
151                     self_get = self.get
152                     for elem, count in iterable.items():
153                         self[elem] = count + self_get(elem, 0)
154                 else:
155                     super(Counter, self).update(iterable) # fast path when counter is empty
156             else:
157                 _count_elements(self, iterable)
158         if kwds:
159             self.update(kwds)
160 
161     def subtract(*args, **kwds):
162         '''Like dict.update() but subtracts counts instead of replacing them.
163         Counts can be reduced below zero.  Both the inputs and outputs are
164         allowed to contain zero and negative counts.
165 
166         Source can be an iterable, a dictionary, or another Counter instance.
167 
168         >>> c = Counter('which')
169         >>> c.subtract('witch')             # subtract elements from another iterable
170         >>> c.subtract(Counter('watch'))    # subtract elements from another counter
171         >>> c['h']                          # 2 in which, minus 1 in witch, minus 1 in watch
172         0
173         >>> c['w']                          # 1 in which, minus 1 in witch, minus 1 in watch
174         -1
175 
176         '''
177         if not args:
178             raise TypeError("descriptor 'subtract' of 'Counter' object "
179                             "needs an argument")
180         self, *args = args
181         if len(args) > 1:
182             raise TypeError('expected at most 1 arguments, got %d' % len(args))
183         iterable = args[0] if args else None
184         if iterable is not None:
185             self_get = self.get
186             if isinstance(iterable, Mapping):
187                 for elem, count in iterable.items():
188                     self[elem] = self_get(elem, 0) - count
189             else:
190                 for elem in iterable:
191                     self[elem] = self_get(elem, 0) - 1
192         if kwds:
193             self.subtract(kwds)
194 
195     def copy(self):
196         'Return a shallow copy.'
197         return self.__class__(self)
198 
199     def __reduce__(self):
200         return self.__class__, (dict(self),)
201 
202     def __delitem__(self, elem):
203         'Like dict.__delitem__() but does not raise KeyError for missing values.'
204         if elem in self:
205             super().__delitem__(elem)
206 
207     def __repr__(self):
208         if not self:
209             return '%s()' % self.__class__.__name__
210         try:
211             items = ', '.join(map('%r: %r'.__mod__, self.most_common()))
212             return '%s({%s})' % (self.__class__.__name__, items)
213         except TypeError:
214             # handle case where values are not orderable
215             return '{0}({1!r})'.format(self.__class__.__name__, dict(self))
216 
217     # Multiset-style mathematical operations discussed in:
218     #       Knuth TAOCP Volume II section 4.6.3 exercise 19
219     #       and at http://en.wikipedia.org/wiki/Multiset
220     #
221     # Outputs guaranteed to only include positive counts.
222     #
223     # To strip negative and zero counts, add-in an empty counter:
224     #       c += Counter()
225 
226     def __add__(self, other):
227         '''Add counts from two counters.
228 
229         >>> Counter('abbb') + Counter('bcc')
230         Counter({'b': 4, 'c': 2, 'a': 1})
231 
232         '''
233         if not isinstance(other, Counter):
234             return NotImplemented
235         result = Counter()
236         for elem, count in self.items():
237             newcount = count + other[elem]
238             if newcount > 0:
239                 result[elem] = newcount
240         for elem, count in other.items():
241             if elem not in self and count > 0:
242                 result[elem] = count
243         return result
244 
245     def __sub__(self, other):
246         ''' Subtract count, but keep only results with positive counts.
247 
248         >>> Counter('abbbc') - Counter('bccd')
249         Counter({'b': 2, 'a': 1})
250 
251         '''
252         if not isinstance(other, Counter):
253             return NotImplemented
254         result = Counter()
255         for elem, count in self.items():
256             newcount = count - other[elem]
257             if newcount > 0:
258                 result[elem] = newcount
259         for elem, count in other.items():
260             if elem not in self and count < 0:
261                 result[elem] = 0 - count
262         return result
263 
264     def __or__(self, other):
265         '''Union is the maximum of value in either of the input counters.
266 
267         >>> Counter('abbb') | Counter('bcc')
268         Counter({'b': 3, 'c': 2, 'a': 1})
269 
270         '''
271         if not isinstance(other, Counter):
272             return NotImplemented
273         result = Counter()
274         for elem, count in self.items():
275             other_count = other[elem]
276             newcount = other_count if count < other_count else count
277             if newcount > 0:
278                 result[elem] = newcount
279         for elem, count in other.items():
280             if elem not in self and count > 0:
281                 result[elem] = count
282         return result
283 
284     def __and__(self, other):
285         ''' Intersection is the minimum of corresponding counts.
286 
287         >>> Counter('abbb') & Counter('bcc')
288         Counter({'b': 1})
289 
290         '''
291         if not isinstance(other, Counter):
292             return NotImplemented
293         result = Counter()
294         for elem, count in self.items():
295             other_count = other[elem]
296             newcount = count if count < other_count else other_count
297             if newcount > 0:
298                 result[elem] = newcount
299         return result
300 
301     def __pos__(self):
302         'Adds an empty counter, effectively stripping negative and zero counts'
303         result = Counter()
304         for elem, count in self.items():
305             if count > 0:
306                 result[elem] = count
307         return result
308 
309     def __neg__(self):
310         '''Subtracts from an empty counter.  Strips positive and zero counts,
311         and flips the sign on negative counts.
312 
313         '''
314         result = Counter()
315         for elem, count in self.items():
316             if count < 0:
317                 result[elem] = 0 - count
318         return result
319 
320     def _keep_positive(self):
321         '''Internal method to strip elements with a negative or zero count'''
322         nonpositive = [elem for elem, count in self.items() if not count > 0]
323         for elem in nonpositive:
324             del self[elem]
325         return self
326 
327     def __iadd__(self, other):
328         '''Inplace add from another counter, keeping only positive counts.
329 
330         >>> c = Counter('abbb')
331         >>> c += Counter('bcc')
332         >>> c
333         Counter({'b': 4, 'c': 2, 'a': 1})
334 
335         '''
336         for elem, count in other.items():
337             self[elem] += count
338         return self._keep_positive()
339 
340     def __isub__(self, other):
341         '''Inplace subtract counter, but keep only results with positive counts.
342 
343         >>> c = Counter('abbbc')
344         >>> c -= Counter('bccd')
345         >>> c
346         Counter({'b': 2, 'a': 1})
347 
348         '''
349         for elem, count in other.items():
350             self[elem] -= count
351         return self._keep_positive()
352 
353     def __ior__(self, other):
354         '''Inplace union is the maximum of value from either counter.
355 
356         >>> c = Counter('abbb')
357         >>> c |= Counter('bcc')
358         >>> c
359         Counter({'b': 3, 'c': 2, 'a': 1})
360 
361         '''
362         for elem, other_count in other.items():
363             count = self[elem]
364             if other_count > count:
365                 self[elem] = other_count
366         return self._keep_positive()
367 
368     def __iand__(self, other):
369         '''Inplace intersection is the minimum of corresponding counts.
370 
371         >>> c = Counter('abbb')
372         >>> c &= Counter('bcc')
373         >>> c
374         Counter({'b': 1})
375 
376         '''
377         for elem, count in self.items():
378             other_count = other[elem]
379             if other_count < count:
380                 self[elem] = other_count
381         return self._keep_positive()
Counter

相关文章:

  • 2022-12-23
  • 2022-02-23
  • 2021-07-24
  • 2021-10-19
  • 2021-05-19
  • 2022-12-23
  • 2021-12-27
猜你喜欢
  • 2021-11-24
  • 2022-01-09
  • 2022-01-14
  • 2021-11-27
  • 2022-01-21
  • 2021-05-23
  • 2022-12-23
相关资源
相似解决方案