collection模塊是對Python的通用內置容器:字典、列表、元組和集合的擴展,它包含一些專業的容器數據類型: Counter(計數器):dict子類,用於計算可哈希性對象的個數。 OrderedDict(有序字典):dict 子類,記錄著數據成員添加的順序。 defaultdict(預設字典 ...
collection模塊是對Python的通用內置容器:字典
、列表、元組和集合的擴展,它包含一些專業的容器數據類型:
- Counter(計數器):dict子類,用於計算可哈希性對象的個數。
- OrderedDict(有序字典):dict 子類,記錄著數據成員添加的順序。
- defaultdict(預設字典):dict 子類,調用一個工廠函數來為dict的values值缺失提供一個預設值。
- namedtuple(可命名元組):工廠函數生成有命名欄位的tuple子類。
- deque(雙向隊列):能在“隊列”兩端快速出隊、入隊的函數,類似於隊列的(list-like)的容器。
- ChainMap:為多個映射創建單一視圖的類字典類型。
UserDict:
將字典包裹起來使得創建字典的子類更容易。UserList
:將列表對象包裹起來使得創建列表的子類更容易。UserString
:將字元串對象包裹起來使得創建字元串的子類更容易。
參考網頁:https://docs.python.org/3.5/library/collections.html
1.計數器(counter)
Counter
是dict
的子類,用於計數可哈希性對象。它是一個無序的容器,元素存儲為字典鍵,計數值存儲為字典值。計數允許任何整數值,包括零或負計數。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
1)計數器的創建
from collections import Counter #Counter 需要申明 a=Counter() # 創建空計數器 b=Counter('aabbbcccc') # 可迭代對象計數的方式創建對象 c = Counter({'red': 4, 'blue': 2}) # 映射方法創建計數器 d = Counter(cats=4, dogs=8) # 鍵值的方法創建計數器
2)計數器元素的刪除
1 a=Counter({'a':2,'b':6,'c':4,'d':0,'e':-2}) 2 print(a) 3 a['a']=0 #修改了計數器元素里的值 4 print(a) 5 del a['b'] #刪除了元素 6 print(a) 7 8 #運行結果 9 Counter({'b': 6, 'c': 4, 'a': 2, 'd': 0, 'e': -2}) 10 Counter({'b': 6, 'c': 4, 'a': 0, 'd': 0, 'e': -2}) 11 Counter({'c': 4, 'a': 0, 'd': 0, 'e': -2})del
3)計數器的部分功能屬性
most_common(self, n=None):
把計數器轉化成列表,元素轉化成元組,返回n個最常見的元素及其計數的列表,從最常見到最少見。如果省略n或為None
,most_common()
返回計數器中所有元素。具有相等計數的元素是任意排序的。
1 a=Counter({'a':2,'b':6,'c':4,'d':0,'e':-2}) 2 b=a.most_common() 3 c=a.most_common(2) 4 print(a) 5 print(b,type(b)) 6 print(c,type(c)) 7 8 #運行結果 9 Counter({'b': 6, 'c': 4, 'a': 2, 'd': 0, 'e': -2}) 10 [('b', 6), ('c', 4), ('a', 2), ('d', 0), ('e', -2)] <class 'list'> 11 [('b', 6), ('c', 4)] <class 'list'>demo
elements(self):
返回一個迭代器,對元素重覆