@@ -683,6 +683,69 @@ def __neg__(self):
683683 '''
684684 return Counter () - self
685685
686+ def _keep_positive (self ):
687+ '''Internal method to strip elements with a negative or zero count'''
688+ nonpositive = [elem for elem , count in self .items () if not count > 0 ]
689+ for elem in nonpositive :
690+ del self [elem ]
691+ return self
692+
693+ def __iadd__ (self , other ):
694+ '''Inplace add from another counter, keeping only positive counts.
695+
696+ >>> c = Counter('abbb')
697+ >>> c += Counter('bcc')
698+ >>> c
699+ Counter({'b': 4, 'c': 2, 'a': 1})
700+
701+ '''
702+ for elem , count in other .items ():
703+ self [elem ] += count
704+ return self ._keep_positive ()
705+
706+ def __isub__ (self , other ):
707+ '''Inplace subtract counter, but keep only results with positive counts.
708+
709+ >>> c = Counter('abbbc')
710+ >>> c -= Counter('bccd')
711+ >>> c
712+ Counter({'b': 2, 'a': 1})
713+
714+ '''
715+ for elem , count in other .items ():
716+ self [elem ] -= count
717+ return self ._keep_positive ()
718+
719+ def __ior__ (self , other ):
720+ '''Inplace union is the maximum of value from either counter.
721+
722+ >>> c = Counter('abbb')
723+ >>> c |= Counter('bcc')
724+ >>> c
725+ Counter({'b': 3, 'c': 2, 'a': 1})
726+
727+ '''
728+ for elem , other_count in other .items ():
729+ count = self [elem ]
730+ if other_count > count :
731+ self [elem ] = other_count
732+ return self ._keep_positive ()
733+
734+ def __iand__ (self , other ):
735+ '''Inplace intersection is the minimum of corresponding counts.
736+
737+ >>> c = Counter('abbb')
738+ >>> c &= Counter('bcc')
739+ >>> c
740+ Counter({'b': 1})
741+
742+ '''
743+ for elem , count in self .items ():
744+ other_count = other [elem ]
745+ if other_count < count :
746+ self [elem ] = other_count
747+ return self ._keep_positive ()
748+
686749
687750########################################################################
688751### ChainMap (helper for configparser and string.Template)
0 commit comments